A book about the command line for humans.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
5.6 KiB

10 years ago
  1. 2. a literary problem
  2. =====================
  3. The [previous chapter](../literary_environment) introduced a bunch of tools
  4. using contrived examples. Now we'll look at a real problem, and work through a
  5. solution by building on tools we've already covered.
  6. So on to the problem: I write poetry.
  7. {rimshot dot wav}
  8. Most of the poems I have written are not very good, but lately I've been
  9. thinking that I'd like to comb through the last ten years' worth and pull
  10. the least-embarrassing stuff into a single collection.
  11. I've hinted at how the contents of my blog are stored as files, but let's take
  12. a look at the whole thing:
  13. $ ls -F ~/p1k3/archives/
  14. 1997/ 2003/ 2009/ bones/ meta/
  15. 1998/ 2004/ 2010/ chapbook/ winfield/
  16. 1999/ 2005/ 2011/ cli/ wip/
  17. 2000/ 2006/ 2012/ colophon/
  18. 2001/ 2007/ 2013/ europe/
  19. 2002/ 2008/ 2014/ hack/
  20. (`ls`, again, just lists files. `-F` tells it to append a character that shows
  21. it what type of file we're looking at, such as a trailing / for directories.
  22. `~` is a shorthand that means "my home directory", which in this case is
  23. `/home/brennen`.)
  24. Each of the directories here holds other directories. The ones for each year
  25. have sub-directories for the months of the year, which in turn contain files
  26. for the days. The files are just little pieces of HTML and Markdown and some
  27. other stuff. Many years ago, before I had much of an idea how to program, I
  28. wrote a script to glue them all together into a web page and serve them up to
  29. visitors. This all sounds complicated, but all it really means is that if I
  30. want to write a blog entry, I just open a file and type some stuff. Here's an
  31. example for March 1st:
  32. <!-- exec -->
  33. $ cat ~/p1k3/archives/2014/3/1
  34. <h1>Saturday, March 1</h1>
  35. <markdown>
  36. Sometimes I'm going along on a Saturday morning, still a little dazed from the
  37. night before, and I think something like "I should just go write a detailed
  38. analysis of hooded sweatshirts". Mostly these thoughts don't survive contact
  39. with an actual keyboard. It's almost certainly for the best.
  40. </markdown>
  41. <!-- end -->
  42. And here's an older one that contains a short poem:
  43. <!-- took this one out of exec block 'cause later i
  44. made a dir out of it... -->
  45. $ cat ~/p1k3/archives/2012/10/9
  46. <h1>tuesday, october 9</h1>
  47. <freeverse>i am a stateful machine
  48. i exist in a manifold of consequence
  49. a clattering miscellany of impure functions
  50. and side effects</freeverse>
  51. Notice that `<freeverse>` bit? It kind of looks like an HTML tag, but it's
  52. not. What it actually does is tell my blog script that it should format the
  53. text it contains like a poem. The specifics don't matter for our purposes
  54. (yet), but this convention is going to come in handy, because the first thing I
  55. want to do is get a list of all the entries that contain poems.
  56. Remember `grep`?
  57. $ grep -ri '<freeverse>' ~/p1k3/archives > ~/possible_poems
  58. Let's step through this bit by bit:
  59. First, I'm asking `grep` to search **r**ecursively, **i**gnoring case.
  60. "Recursively" just means that every time the program finds a directory, it
  61. should descend into that directory and search in any files there as well.
  62. grep -ri
  63. Next comes a pattern to search for. It's in single quotes because the
  64. characters `<` and `>` have a special meaning to the shell, and here we need
  65. the shell to understand that it should treat them as literal angle brackets
  66. instead.
  67. '<freeverse>'
  68. This is the path I want to search:
  69. ~/p1k3/archives
  70. Finally, because there are so many entries to search, I know the process will
  71. be slow and produce a large list, so I tell the shell to redirect it to a file
  72. called `possible_poems` in my home directory:
  73. > ~/possible_poems
  74. This is quite a few instances...
  75. $ wc -l ~/possible_poems
  76. 679 /home/brennen/possible_poems
  77. ...and it's also not super-pretty to look at:
  78. $ head -5 ~/possible_poems
  79. /home/brennen/p1k3/archives/2011/10/14:<freeverse>i've got this friend has a real knack
  80. /home/brennen/p1k3/archives/2011/4/25:<freeverse>i can't claim to strive for it
  81. /home/brennen/p1k3/archives/2011/8/10:<freeverse>one diminishes or becomes greater
  82. /home/brennen/p1k3/archives/2011/8/12:<freeverse>
  83. /home/brennen/p1k3/archives/2011/1/1:<freeverse>six years on
  84. Still, it's a decent start. I can see paths to the files I have to check, and
  85. usually a first line. Since I use a fancy text editor, I can just go down the
  86. list opening each file in a new window and copying the stuff I'm interested in
  87. to a new file.
  88. This is good enough for government work, but what if instead of jumping around
  89. between hundreds of files, I'd rather read everything in one file and just weed
  90. out the bad ones as I go?
  91. $ cat `grep -ril '<freeverse>' ~/p1k3/archives` > ~/possible_poems_full
  92. This probably bears some explaining. `grep` is still doing all the real work
  93. here. The main difference from before is that `-l` tells grep to just list any
  94. files it finds which contain a match.
  95. `grep -ril '<freeverse>' ~/p1k3/archives`
  96. Notice those backticks around the grep command? This part is a little
  97. trippier. It turns out that if you put backticks around something in a
  98. command, it'll get executed and replaced with its result, which in turn gets
  99. executed as part of the larger command. So what we're really saying is
  100. something like:
  101. $ cat [all of the files in the blog directory with <freeverse> in them]
  102. Did you catch that? I just wrote a command that rewrote itself as a
  103. _different_, more specific command. And it appears to have worked on the
  104. first try:
  105. $ wc ~/possible_poems_full
  106. 17628 80980 528699 /home/brennen/possible_poems_full
  107. Welcome to wizard school.