I love working in the shell. Mastery of shell lets you get things done in seconds, rather than minutes or hours, if you chose to write a program instead.
In this article I'd like to explain the top one-liners from the commandlinefu.com. It's a user-driven website where people get to choose the best and most useful shell one-liners.
But before I do that, I want to take the opportunity and link to a few of my articles that I wrote some time ago on working efficiently in the command line:
Update: Russian translation now available.
And now the explanation of top one-liners from commandlinefu.
$ sudo !!
We all know what the sudo
command does - it runs the command as another user, in this case, it runs the command as superuser because no other user was specified. But what's really interesting is the bang-bang!!
part of the command. It's called the event designator. An event designator references a command in shell's history. In this case the event designator references the previous command. Writing !!
is the same as writing !-1
. The -1
refers to the last command. You can generalize it, and write !-n
to refer to the n-th previous command. To view all your previous commands, type history
.
This one-liner is actually really bash-specific, as event designators are a feature of bash.
I wrote about event designators in much more detail in my article "The Definitive Guide to Bash Command Line History." The article also comes with a printable cheat sheet for working with the history.
$ python -m SimpleHTTPServer
This one-liner starts a web server on port 8000 with the contents of current directory on all the interfaces (address 0.0.0.0), not just localhost. If you have "index.html
" or "index.htm
" files, it will serve those, otherwise it will list the contents of the currently working directory.
It works because python comes with a standard module called SimpleHTTPServer
. The -m
argument makes python to search for a module named SimpleHTTPServer.py
in all the possible system locations (listed in sys.path
and $PYTHONPATH
shell variable). Once found, it executes it as a script. If you look at the source code of this module, you'll find that this module tests if it's run as a script if __name__ == '__main__'
, and if it is, it runs the test()
method that makes it run a web server in the current directory.
To use a different port, specify it as the next argument:
$ python -m SimpleHTTPServer 8080
This command runs a HTTP server on all local interfaces on port 8080.
:w !sudo tee %
This happens to me way too often. I open a system config file in vim and edit it just to find out that I don't have permissions to save it. This one-liner saves the day. Instead of writing the while to a temporary file :w /tmp/foobar
and then moving the temporary file to the right destination mv /tmp/foobar /etc/service.conf
, you now just type the one-liner above in vim and it will save the file.
Here is how it works, if you look at the vim documentation (by typing :he :w
in vim), you'll find the reference to the command :w !{cmd}
that says that vim runs {cmd}
and passes it the contents of the file as standard input. In this one-liner the {cmd}
part is the sudo tee %
command. It runs tee %
as superuser. But wait, what is %
? Well, it's a read-only register in vim that contains the filename of the current file! Therefore the command that vim executes becomes tee current_filename
, with the current directory being whatever the current_file
is in. Now what does tee
do? The tee
command takes standard input and write it to a file! Rephrasing, it takes the contents of the file edited in vim, and writes it to the file (while being root)! All done!
$ cd -
Everyone knows this, right? The dash "-
" is short for "previous working directory." The previous working directory is defined by $OLDPWD
shell variable. After you use the cd
command, it sets the $OLDPWD
environment variable, and then, if you type the short version cd -
, it effectively becomes cd $OLDPWD
and changes to the previous directory.
To change to a directory named "-
", you have to either cd to the parent directory and then do cd ./-
or do cd /full/path/to/-
.
$ ^foo^bar^
This is another event designator. This one is for quick substitution. It replaces foo
with bar
and repeats the last command. It's actually a shortcut for !!:s/foo/bar/
. This one-liner applies the s
modifier to the !!
event designator. As we learned from one-liner #1, the !!
event designator stands for the previous command. Now the s
modifier stands for substitute (greetings to sed) and it substitutes the first word with the second word.
Note that this one-liner replaces just the first word in the previous command. To replace all words, add the g
modifer (g
for global):
$ !!:gs/foo/bar
This one-liner is also bash-specific, as event designators are a feature of bash.
Again, see my article "The Definitive Guide to Bash Command Line History." I explain all this stuff in great detail.
$ cp filename{,.bak}
This one-liner copies the file named filename
to a file named filename.bak
. Here is how it works. It uses brace expansion to construct a list of arguments for the cp
command. Brace expansion is a mechanism by which arbitrary strings may be generated. In this one-liner filename{,.bak}
gets brace expanded to filename filename.bak
and puts in place of the brace expression. The command becomes cp filename filename.bak
and file gets copied.
Talking more about brace expansion, you can do all kinds of combinatorics with it. Here is a fun application:
$ echo {a,b,c}{a,b,c}{a,b,c}
It generates all the possible strings 3-letter from the set {a, b, c}
:
aaa aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cab cac cba cbb cbc cca ccb ccc
And here is how to generate all the possible 2-letter strings from the set of {a, b, c}
:
$ echo {a,b,c}{a,b,c}
It produces:
aa ab ac ba bb bc ca cb cc
If you liked this, you may also like my article where I defined a bunch of set operations (such as intersection, union, symmetry, powerset, etc) by using just shell commands. The article is called "Set Operations in the Unix Shell." (And since I have sets in the shell, I will soon write articles on on "Combinatorics in the Shell" and "Algebra in the Shell". Fun topics to explore. Perhaps even "Topology in the Shell" :))
$ mtr google.com
MTR, bettern known as "Matt's Traceroute" combines both traceroute
and ping
command. After each successful hop, it sends a ping request to the found machine, this way it produces output of bothtraceroute
and ping
to better understand the quality of link. If it finds out a packet took an alternative route, it displays it, and by default it keeps updating the statistics so you knew what was going on in real time.
$ !whatever:p
Another use of event designators. The !whatever
designator searches the shell history for the most recently executed command that starts with whatever
. But instead of executing it, it prints it. The :p
modifier makes it print instead of executing.
This one-liner is bash-specific, as event designators are a feature of bash.
Once again, see my article "The Definitive Guide to Bash Command Line History." I explain all this stuff in great detail.
$ ssh-copy-id remote-machine
This one-liner copies your public-key, that you generated with ssh-keygen
(either SSHv1 file identity.pub or SSHv2 file id_rsa.pub) to the remote-machine
and places it in ~/.ssh/authorized_keys
file. This ensures that the next time you try to log into that machine, public-key authentication (commonly referred to as "passwordless authentication.") will be used instead of the regular password authentication.
If you wished to do it yourself, you'd have to take the following steps:
your-machine$ scp ~/.ssh/identity.pub remote-machine: your-machine$ ssh remote-machine remote-machine$ cat identity.pub >> ~/.ssh/authorized_keys
This one-liner saves a great deal of typing. Actually I just found out that there was a shorter way to do it:
your-machine$ ssh remote-machine 'cat >> .ssh/authorized_keys' < .ssh/identity.pub
$ ffmpeg -f x11grab -s wxga -r 25 -i :0.0 -sameq /tmp/out.mpg
A pure coincidence, I have done so much video processing with ffmpeg that I know what most of this command does without looking much in the manual.
The ffmpeg generally can be descibed as a command that takes a bunch of options and the last option is the output file. In this case the options are -f x11grab -s wxga -r 25 -i :0.0 -sameq
and the output file is /tmp/out.mpg
.
Here is what the options mean:
-f x11grab
makes ffmpeg to set the input video format as x11grab. The X11 framebuffer has a specific format it presents data in and it makes ffmpeg to decode it correctly.-s wxga
makes ffmpeg to set the size of the video to wxga which is shortcut for 1366x768. This is a strange resolution to use, I'd just write -s 800x600
.-r 25
sets the framerate of the video to 25fps.-i :0.0
sets the video input file to X11 display 0.0 at localhost.-sameq
preserves the quality of input stream. It's best to preserve the quality and post-process it later. You can also specify ffmpeg to grab display from another x-server by changing the -i :0.0
to -i host:0.0
.
If you're interested in ffmpeg, here are my other articles on ffmpeg that I wrote while ago:
PS. This article was so fun to write, that I decided to write several more parts. Tune in the next time for "The Next Top Ten One-Liners from CommandLineFu Explained" :)
Have fun. See ya!
http://www.catonmat.net/blog/top-ten-one-liners-from-commandlinefu-explained/