Hide

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.


If you have a new feature suggestion or find a bug, please get in touch via http://commandlinefu.uservoice.com/

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.

Hide

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:

Hide

News

2011-03-12 - Confoo 2011 presentation
Slides are available from the commandlinefu presentation at Confoo 2011: http://presentations.codeinthehole.com/confoo2011/
2011-01-04 - Moderation now required for new commands
To try and put and end to the spamming, new commands require moderation before they will appear on the site.
2010-12-27 - Apologies for not banning the trolls sooner
Have been away from the interwebs over Christmas. Will be more vigilant henceforth.
2010-09-24 - OAuth and pagination problems fixed
Apologies for the delay in getting Twitter's OAuth supported. Annoying pagination gremlin also fixed.
Hide

Tags

Hide

Functions

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
-3

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
0

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
7

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
30

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
0

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
-1

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
2

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
26

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

CTRL+Z

fg; echo "finished" | sendmail me@example.com

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
3

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
1

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
1

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
6

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
7

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,"."){@a=readdir D;print $#a-1,"\n"}'
2009-07-23 20:14:33
User: recursiverse
Functions: perl
Tags: perl ls
1
time perl -e 'if(opendir D,"."){@a=readdir D;print $#a - 1,"\n"}'

205413

real 0m0.497s

user 0m0.220s

sys 0m0.268s

time { ls |wc -l; }

205413

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; }

205414

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"'

205414

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
4

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
15

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
4

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

ion@atomos:~[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
16

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
41

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
5

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.