您的位置:首页 > 大数据 > 人工智能

Top Ten One-Liners from CommandLineFu Explained

2013-09-11 10:06 423 查看


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:

Working Efficiently in Bash (Part I).

Working Efficiently in Bash (Part
II).

The Definitive Guide
to Bash Command Line History.

A fun article on Set Operations in the Shell.

Another fun article
on Solving Google Treasure Hunt in the Shell.

Update: Russian translation
now available.

And now the explanation of top one-liners from commandlinefu.


#1. Run the last command as root

$ 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.


#2. Serve the current directory at http://localhost:8000/

[code]$ 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.


#3. Save a file you edited in vim without the needed permissions

: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!


#4. Change to the previous working directory

$ 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/-
.


#5. Run the previous shell command but replace string "foo" with "bar"

$ ^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.


#6. Quickly backup or copy a file

$ 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"
:))


#7. mtr - traceroute and ping combined

$ 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 both
traceroute
 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.


#8. Find the last command that begins with "whatever," but avoid running it

$ !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.


#9. Copy your public-key to remote-machine for public-key authentication

$ 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


#10. Capture video of a linux desktop

$ 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:

How to Extract Audio
Tracks from YouTube Videos

Converting YouTube
Flash Videos to a Better Format with ffmpeg

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/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: