On my nightstand I have a pile of books - a pile of guilt as Scott Hanselman refers to it - in this pile lies a book called “The Pragmatic Programmer” which I pick up every now and then to read before I go to sleep. There is a short section in the book called “Shell games” where the authors tells us about the importance of learning to use the command line well - they compare it to the woodworkers workbench.
I tend agree, while GUIs in many cases are great and lets you perform tasks without memorizing a bunch of different commands, the command line is often a faster way - and lets you automate timewasting tasks.
I write this post as I feel that I can benefit from taking my command line kung-fu to a higher level, and past experience tells me that writing about a subject is a great way to learn. Hopefully readers (if any) feel that they can take something away from this post as well.
I feel that it’s best to put things in a meaningful context, and as I enjoy Node.js it will have to fill that role. Lets say that we are working on a big Node.js project and want to know what kind of dependencies we require throughout the project.
We are standing in the project directory. The tree command, which can be used to list the files in the current directory and subdirectories, gives us the following output:
.
├── app.js
└── lib
└── helpers.js
1 directory, 2 files
Lets say that the app.js file contains the following:
var express = require('express');
var helpers = require('./lib/helpers');
console.log('Hello');
To get dependencies we need to look for the lines with require statements. This is where the grep
command comes in handy.
If we were to execute grep "require" app.js
we would receieve the following output:
var express = require('express');
var helpers = require('./lib/helpers');
So far so good! But what if we also want to retrieve the contents of the helpers.js file inside of the lib directory? We could execute grep with the recursive parameter - grep -R "require" .
. This gives us the contents of that file as well, problem is that this is not limited to only js-files. If there is another file type containing a line with “require” we will retrieve these as well. So how does we limit the range to js-files?
We could use grep -R --include="*.js" "require" .
to specify that we want files with the js extension. Or why not use the ack utility? It’s actually designed for code search. Easy as ack --js require
- so fresh and so clean! It searches recursively by defauilt and ignore folders such as .git etc.
Executing the command above, we receive something along the lines of:
app.js
1:var express = require('express');
2:var helpers = require('./lib/helpers');
lib/helpers.js
1:var moment = require('moment');
What if we only want text inside of the parentheses? So for var moment = require('moment')
we only want the moment
part.
One way that I found is to use awk with the field separator flag, such as: ack --js require | awk -F\' '{ print $2 }'
. The -F flag tells it to split rows on the single quote (in our case). The later part '{ print $2 }'
takes the result and prints the part between single quotes - $1 will result in the part before a single quote, $2 the second part, and $3 gives us the last part (which will be );
).
case.
Another way to achieve the same results is to use the cut command, which is a bit more straight forward - according to me at least. If we run ack --js require | cut -d\' -f2
we get the same results:
express
./lib/helpers
moment
I will end this post at that.