If you're a developer you will likely be spending a lot of time in the command line. Here's a few tips and tricks I've learned over the years.
Basic commands you should know
If you want to list all of the directories and files in the current directory you would use the ls command:
$ ls /var/log
In programming we often have a lot of configuration files that are hidden. These are referred to as dotfiles because they start with a dot e.g. .file You can modify the list command by using the -a (all) flag e.g. ls -a which will show all files including your hidden config files:
$ ls -a
Now suppose you want to delete a directory, but it has files inside of it. Instead of reaching for finder, you can use the rm command, but that will only delete single files or empty directories. If you need to delete the entire directory you can use the -r (recursive) flag e.g. rm -r which will delete all of the files in the directory as well as the directory itself. You can also use wildcard expressions to match specific files in a directory too. Perhaps you want to delete all the text files:
Occasionally you'll find that some of the files are write-protected which will prompt you to confirm you really want to delete the file. If you are recursively deleting write-protected files it can get really tedious inputting y to confirm their deletion over-and-over. To get around this we can supply the -f (force) flag to tell the remove command to go ahead without asking:
$ rm -rf dirname/write-protected.*.txt
=> Deleted 10 write protected files without bothering you for permission
Some shell shortcuts
Ever typed a command and forgot sudo? Did you know you can use !! to replay the last command. This is really useful for sudoing commands that failed:
$ rm -rf /important-directory
=> permission denied
$ sudo !!
=> I'm sorry, I didn't realize it was you, go right ahead
You can view a history of all your commands by typing history into the command line:
=> 1 ls /var/log
=> 2 ls -a
=> 3 rm -r dirname/*.txt
=> 4 rm -rf dirname/write-protected.*.txt
=> 5 rm -rf /important-directory
=> 6 sudo rm -rf /important-directory
You can also use !-n (where n is a number) to copy the command you used n commands ago:
You can also use !substring to use the last command that started with that string:
$ ffmpeg -i video.flv video.mpeg
=> video.flv not found
$ cd ..
=> thumbnails/ videos/
$ cd videos
=> converting video.flv to video.mpeg
Then we can do some more adventurous things like replacing text in the previous command:
$ rm -r dir/foo/*.rb
=> removed all ruby files in dir/foo/
=> removed all ruby files in dir/bar/
Some Rails tricks I use often
Adding a file to .gitignore without opening the editor is as simple as shoveling it in. (NOTE be careful not to use > or you'll overwrite the entire file - we want >> to append the text):
$ "public/assets" >> .gitignore
=> appended "public/assets" to .gitignore
Need to find a route in your Rails application? You know some substring in the route but not sure the exact route. You can grep for it by piping the output from bin/rails routes to grep and then use the substring to narrow down the routes:
$ bin/rails routes | grep auth
=> oauth_token POST /api/v1/oauth/token(.:format) doorkeeper/tokens#create
=> oauth_revoke POST /api/v1/oauth/revoke(.:format) doorkeeper/tokens#revoke
=> oauth_introspect POST /api/v1/oauth/introspect(.:format) doorkeeper/tokens#introspect
Store the output of a script in a file by redirecting the output like we did before when adding public/assets to our .gitignore. However, this time we'll overwrite the whole file:
$ ruby ./scripts/1_million_dollars.rb > ./log/1_million_dollars.txt
=> No output here
$ cat ./log/did_i_get_1_million_dollars.txt
=> Don't you think we should maybe ask for more than a million dollars?
=> A million dollars isn't exactly a lot of money these days.
=> Virtucon alone makes over 9 billion dollars a year!
Or if you want to log theSTDERR output to its own file:
$ ruby ./scripts/raise_allota_errors.rb 2> ./log/allota_errors.text
=> STDOUT output here
$ cat ./log/allota_errors.text
=> STDERR output here
You can use less to view a file. While less is running you use /substring to search the file, or up and down arrows to navigate around. Less is very similar to more but is faster because it doesn't load the full file into memory.
$ less ./log/production.log
You can also use tail to watch the "tail" of a file in real-time, this is useful for watching logs while they are being written. Make sure to use the "follow" flag to watch it in real-time or you'll only see the last few lines of the file (If you're on a machine that is rotating the logs, you can use -F to keep watching the file even after it has been recreated during rotation):
Ever needed to count how many lines are in a file? You can use wc (word-count) and pass the -l (lines) flag to count the lines:
$ wc -l ./users_dump.csv
You can also use this to count how many lines in the output of a command e.g. find out how many files are in a directory with:
$ ls ./node_modules | wc -l
Ever needed to write a long command and feel frustrated with the editing experience in your terminal? Open your EDITOR and edit the command instead by pressing ctrl-x ctrl-e:
$ some-long command ops I spelled that thing wrong ctrl-x ctrl-e
#> *opens your EDITOR*
#< save and close your editor to re-enter shell
$ some-long command I spelled correctly now
For the above to work you'll need to export EDITOR=your_editor in your .bashrc or .zshrc. Some editors will need to use wait mode to return to the terminal after editing. If you're a MacVim user you'll need to pass a command to run after VimLeave like I have here:
export EDITOR='mvim -f -c "au VimLeave * !open -a iTerm"'
I know shell fu
The terminal is incredible! It's where we began but continues to be one of the most powerful tools in my day-to-day activities. There's loads of stuff I haven't even mentioned in this article. I recommend reading more if any of this interests you. The shell has been around as long as modern computers so there's a huge amount of information available. If you know any shell tricks I'd love to hear them.