What's this?

commandlinefu.com is the place to record those command-line gems that you return to again and again.

Delete that bloated snippets file you've been using and share your personal repository with the world. That way others can gain from your CLI wisdom and you from theirs too. All commands can be commented on, discussed and voted up or down.

Get involved!

You can sign-in using OpenID credentials, or register a traditional username and password.

First-time OpenID users will be automatically assigned a username which can be changed after signing in.

UpGuard checks and validates configurations for every major OS, network device, and cloud provider.

Stay in the loop…

Follow the Tweets.

Every new command is wrapped in a tweet and posted to Twitter. Following the stream is a great way of staying abreast of the latest commands. For the more discerning, there are Twitter accounts for commands that get a minimum of 3 and 10 votes - that way only the great commands get tweeted.

» http://twitter.com/commandlinefu
» http://twitter.com/commandlinefu3
» http://twitter.com/commandlinefu10

Subscribe to the feeds.

Use your favourite RSS aggregator to stay in touch with the latest commands. There are feeds mirroring the 3 Twitter streams as well as for virtually every other subset (users, tags, functions,…):

Subscribe to the feed for:



May 19, 2015 - A Look At The New Commandlinefu
I've put together a short writeup on what kind of newness you can expect from the next iteration of clfu. Check it out here.
March 2, 2015 - New Management
I'm Jon, I'll be maintaining and improving clfu. Thanks to David for building such a great resource!

Top Tags



Commands by recursiverse from sorted by
Terminal - Commands by recursiverse - 22 results
ls | perl -lne '++$x{lc $1} if /[.](.+)$/ }{ print for keys %x'
2010-08-13 20:05:15
User: recursiverse
Functions: ls perl

All with only one pipe. Should be much faster as well (sort is slow). Use find instead of ls for recursion or reliability.

Edit: case insensitive

find /var/log/apache2 -name 'access.log*gz' -exec zcat {} \; -or -name 'access.log*' -exec cat {} \;
2010-06-19 08:35:12
User: recursiverse
Functions: cat find zcat

This command allows you to stream your log files, including gziped files, into one stream which can be piped to awk or some other command for analysis.

Note: if your version of 'find' supports it, use:

find /var/log/apache2 -name 'access.log*gz' -exec zcat {} + -or -name 'access.log*' -exec cat {} +
echo $((($(date +%s)-$(date +%s -d "march 1"))/86400))
2010-06-04 21:41:07
User: recursiverse
Functions: date echo

You can also do this for seconds, minutes, hours, etc... Can't use dates before the epoch, though.

ssh host -l user $(<cmd.txt)
2010-06-04 17:47:00
User: recursiverse
Functions: host ssh

Much simpler method. More portable version: ssh host -l user "`cat cmd.txt`"

perl -e 'system @ARGV, <STDIN>' ssh host -l user < cmd.txt
2010-06-04 17:27:20
User: recursiverse
Functions: host perl ssh

I was tired of the endless quoting, unquoting, re-quoting, and escaping characters that left me with working, but barely comprehensible shell one-liners. It can be really frustrating, especially if the local and remote shells differ and have their own escaping and quoting rules. I decided to try a different approach and ended up with this.

awk 'BEGIN{ORS=""}NR!=1&&FNR==1{print "\n"}{print}END{print "\n"}' *.txt
2010-05-24 19:22:35
User: recursiverse
Functions: awk

Problem: you want to output one line per file. you can't just 'tr -d' because you want one line per file and you don't want to use a loop.

Solution: use awk to print each line without the record separator and a newline after each file.

$ python -u script.py
2010-05-20 17:53:47
User: recursiverse
Functions: python

You have a python script that slowly prints output, you want to pipe the output to grep or tee, and you are impatient and want to watch the results right away. Rather than modify your script (making it slightly less efficient), use the -u option to have the output unbuffered.

<ctrl+z> fg; notify_me
2010-05-20 16:16:43
User: recursiverse

If you want to be notified when a long-running command is finished, but you have already started it:


fg; echo "finished" | sendmail [email protected]

I use a script to post a tweet, which sends me a txt:

fg; echo "finished" | tweet
ffmpeg -i broken.flv -acodec copy -vcodec copy fixed.flv
2010-05-08 20:31:37
User: recursiverse

Rebuild flv files that are broken (can't seek). This method probably works for other video/audio formats that can become broken in the same way.

comm file1 file2 | sed -e 's/^[^\t].*/\x1b[33m&\x1b[0m/' -e 's/^\t[^\t].*/\x1b[36m&\x1b[0m/' -e 's/^\t\t[^\t].*/\x1b[32m&\x1b[0m/'
2010-05-07 00:14:31
User: recursiverse
Functions: comm sed

It just colorizes the line based on if it has 0, 1 or 2 tabs at the beginning of the line. Won't work so well if lines already begin with tabs (too bad comm doesn't have an option to substitute \t for something else).

Don't forget comm needs input files to be sorted. You can use a shortcut like this with bash: comm

objdump -b binary -m i386 -D shellcode.bin
2010-04-27 11:11:36
User: recursiverse
Functions: objdump

The options -b binary and -m are needed for disassembling raw machine code when it is not part of a full binary executable with proper headers.

ps -C command
2009-08-14 15:30:42
User: recursiverse
Functions: ps

preferred way to query ps for a specific process name (not supported with all flavors of ps, but will work on just about any linux afaik)

find public_html/stuff -type d -exec chmod 755 {} + -or -type f -exec chmod 644 {} +
2009-07-26 11:10:10
User: recursiverse
Functions: chmod find

Good for fixing web permissions. You might also want to do something like this and skip files or directories that begin with a period:

find public_html/stuff -not -name ".*" \( -type d -exec chmod 755 {} + -o -type f -exec chmod 644 {} + \)

...or include a special case for scripts:

find public_html/stuff -type d -exec chmod 755 {} + -or -type f -name "*.pl" -exec chmod 755 {} + -or -exec chmod 644 {} +
install -o user -g group -m 0700 -d /path/to/newdir
man perlcheat | col -b > perlcheat.txt
perl -e 'if(opendir D,".")[email protected]=readdir D;print $#a-1,"\n"}'
2009-07-23 20:14:33
User: recursiverse
Functions: perl
Tags: perl ls
time perl -e 'if(opendir D,".")[email protected]=readdir D;print $#a - 1,"\n"}'


real 0m0.497s

user 0m0.220s

sys 0m0.268s

time { ls |wc -l; }


real 0m3.776s

user 0m3.340s

sys 0m0.424s


** EDIT: turns out this perl liner is mostly masturbation. this is slightly faster:

find . -maxdepth 1 | wc -l

sh-3.2$ time { find . -maxdepth 1|wc -l; }


real 0m0.456s

user 0m0.116s

sys 0m0.328s

** EDIT: now a slightly faster perl version

perl -e 'if(opendir D,"."){++$c foreach readdir D}print $c-1,"\n"'

sh-3.2$ time perl -e 'if(opendir D,"."){++$c foreach readdir D}print $c-1,"\n"'


real 0m0.415s

user 0m0.176s

sys 0m0.232s

sed -n 's/.*<foo>\([^<]*\)<\/foo>.*/\1/p'
2009-07-23 07:59:30
User: recursiverse
Functions: sed

Limited, but useful construct to extract text embedded in XML tags. This will only work if bar is all on one line.

If nobody posts an alternative for the multiline sed version, I'll figure it out later...

tail -F file
2009-07-23 07:37:11
User: recursiverse
Functions: tail
Tags: tail logs

If you use 'tail -f foo.txt' and it becomes temporarily moved/deleted (ie: log rolls over) then tail will not pick up on the new foo.txt and simply waits with no output.

'tail -F' allows you to follow the file by it's name, rather than a descriptor. If foo.txt disappears, tail will wait until the filename appears again and then continues tailing.

[[ "$WINDOW" ]] && PS1="\u@\h:\w[$WINDOW]\$ "
2009-07-23 06:46:19
User: recursiverse
Tags: bash screen shell

Add this to your $HOME/.bashrc file. It will only set this prompt if it is running inside screen ($WINDOW var is set)

Looks like this...

[email protected]:~[2]$
awk '{print NR": "$0; for(i=1;i<=NF;++i)print "\t"i": "$i}'
2009-07-23 06:25:31
User: recursiverse
Functions: awk
Tags: awk

Breaks down and numbers each line and it's fields. This is really useful when you are going to parse something with awk but aren't sure exactly where to start.

ssh -t remote_host screen -r
2009-07-23 06:15:04
User: recursiverse
Functions: screen ssh
Tags: ssh screen

Directly attach a remote screen session (saves a useless parent bash process)

tar c folder_to_encrypt | openssl enc -aes-256-cbc -e > secret.tar.enc
2009-07-23 06:03:39
User: recursiverse
Functions: c++ tar

command to decrypt:

openssl enc -aes-256-cbc -d < secret.tar.enc | tar x

Of course, don't forget to rm the original files ;) You may also want to look at the openssl docs for more options.