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 bartonski from sorted by
Terminal - Commands by bartonski - 44 results
o=0; git log --oneline | while read l; do printf "%+9s %s\n" "HEAD~${o}" "$l"; o=$(($o+1)); done | less
ir() { perl -pne 's/(.)(.*)/\[\1]\2/' <<< "[email protected]" ;}
2015-07-25 14:13:33
User: bartonski
Functions: perl
Tags: ps

Note that `grep "$(ir foo)"` really doesn't save any typing, but wrapping this inside a second shell function will:

psg() { grep "$(ir \"[email protected]\")" ;}
mojo get <URL> 'a[href]' attr href
tstouch() { [[ $1 =~ $2 ]] && touch -t ${BASH_REMATCH[1]} $1; }
2013-10-01 20:00:34
User: bartonski
Functions: touch
Tags: bash touch

tstouch takes two arguments: a filename containing a timestamp, and an extended regular expression with the parenthesized section matching a timestamp of the form YYYYMMDDhhmm or YYYYMMDDhhmm.ss.

It then touches the file with that timestamp.

man ls | egrep "^([A-Z]| [A-Z])"
2013-01-09 17:12:03
User: bartonski
Functions: egrep ls man

Uses the formatting of a man page to show an outline of its headers and sub-headers.

screen !!
2012-10-15 12:58:38
User: bartonski
Functions: screen

I often find myself wanting to open screen on whatever command I'm currently running. Unfortunately, opening a fresh screen session spawns a new bash session, which doesn't keep my history, so calling screen directly with the previous command is the only way to go.

tag() { local t="$HOME/tags/$1"; [ -d $t ] || mkdir -p $t; shift; ln $* $t;}
2012-02-08 12:40:45
User: bartonski
Functions: ln mkdir

The tag function takes a tag name as its first argument, then a list of files which take that tag. The directory $HOME/tags/tagname will then hold symbolic links to each of the tagged files. This function was inspired by tmsu (found at https://bitbucket.org/oniony/tmsu/wiki/Home).


tag dog airedale.txt .shizturc weimeraner.pl

This will create $HOME/tags/dog which contains symbolic links to airedale.txt .shizturc and weimeraner.pl

lastfile () { find ${1:-.} -maxdepth 1 -type f -printf "%T+ %p\n" | sort -n | tail -n1 | sed 's/[^[:space:]]\+ //'; }
2011-10-17 16:08:02
User: bartonski
Functions: find sed sort tail

Takes a directory name as an argument (defaults to current directory if no arguments are given). Prints the newest file in the directory.

dups() { sort "[email protected]" | uniq -d; }
shebang() { if i=$(which $1); then printf '#!%s\n\n' $i > $2 && vim + $2 && chmod 755 $2; else echo "'which' could not find $1, is it in your \$PATH?"; fi; }
2011-03-09 14:47:32
User: bartonski
Functions: chmod echo printf vim which

The first argument is the interpreter for your script, the second argument is the name of the script to create.

numpages() { echo $(($(wc -l $* | sed -n 's/ total$//p')/60)); }
2011-02-28 20:08:26
User: bartonski
Functions: echo sed wc

This gives a very rough estimate of how many pages your text files will print on. Assumes 60 lines per page, and does not take long lines into account.

ls -l --time-style=+"%Y-%m-%d %H:%M:%S"
2011-02-10 17:15:37
User: bartonski
Functions: ls

the --time-style argument to 'ls' takes several possible modifiers: full-iso, long-iso, iso, locale, +FORMAT.

The +FORMAT modifier uses the same syntax as date +FORMAT.

--time-style=+"%Y-%m-%d %H:%M:%S" strikes a happy medium between accuracy and verbosity:

ls -lart --time-style=long-iso

doesn't show time down to the nearest second,

ls -lart --time-style=full-iso

displays time to 10E-9 second resolution, but with no significant digits past the full seconds, also showing the timezone:

-rw-r--r-- 1 bchittenden bchittenden 0 2011-02-10 12:07:55.000000000 -0500 bar
screencast() { arecord -R 1000 -f cd -t wav $1.wav & RECPID=$!; echo "Starting screencast in new shell. Exit subshell to quit."; script -t 2> $1.timing -a $1.session; kill $RECPID; }
2011-01-20 14:35:47
User: bartonski
Functions: arecord cd echo kill script

This shell function takes a single argument, which is used as the base name of the .wav, .timing and .session files created. To create a screencast:

screencast test

type and talk ...

then type 'exit' or to exit the screencast.

test.wav will contain the audio from your screencast.

test.session will contain text and control characters needed to paint the screen

test.timing will contain timing information needed to synch individual keystrokes in test.session with the audio.

to play back:

aplay test.wav & scriptreplay test.{timing,session}

NOTE: because the shell function uses the variable "$!", and bash likes to expand '!' during history expansion, you will need to turn off bash's history before you enter the shell function.

This can be achieved using the command

set +H
xdg-open $(svn info | sed -n '/URL:/s/URL: //p')
vimcmd() { $1 > $2 && vim $2; }
2010-12-16 21:51:35
User: bartonski
Functions: vim

This is one of those 'nothing' shell functions ...which I use all the time.

If the command contains spaces, it must be quoted, e.g.

vimcmd 'svn diff' /tmp/svndiff.out

If I want to keep the output of the command that I'm running, I use vimcmd. If I don't need to keep the output, I use this:

vim <( ... my command ... )
find . ! -name "." -print0 | xargs -0 -I '{}' mv -n '{}' ..; rmdir "$PWD"
2010-12-15 22:12:06
User: bartonski
Functions: find mv rmdir xargs

Robust means of moving all files up by a directory. Will handle dot files, filenames containing spaces, and filenames with almost any printable characters. Will not handle filenames containing a single-quote (but if you are moving those, it's time to go yell at whoever created them in the first place).

qrurl() { curl "http://chart.apis.google.com/chart?chs=150x150&cht=qr&chld=H%7C0&chl=$1" -o qr.$(date +%Y%m%d%H%M%S).png; }
2010-12-15 04:40:22
User: bartonski
Functions: date

QR codes are those funny square 2d bar codes that everyone seems to be pointing their smart phones at.

Try the following...

qrurl http://xkcd.com

Then open qr.*.png in your favorite image viewer.

Point your the bar code reader on your smart phone at the code, and you'll shortly be reading xkcd on your phone.

URLs are not the only thing that can be encoded by QR codes... short texts (to around 2K) can be encoded this way, although this function doesn't do any URL encoding, so unless you want to do that by hand it won't be useful for that.

log() { (echo "\$ [email protected]";[email protected]) | logger -t $USER; }
2010-09-25 20:43:22
User: bartonski
Functions: echo logger

This command is useful if you want to copy the output of a series of commands to a file, for example if you want to pastebin the output from 'uname -a', 'lspci -vvv' and 'lsmod' for video driver trouble-shooting on your favorite Linux forum.

'log' takes all the following arguments as a command to execute, with STDOUT sent to /var/log/user.log. The command is echoed to the log before it is executed.

The advantages of using logger (as opposed to appending output from commands to a file) are 1) commands are always appended to the logs... you don't have to worry about clobbering your log file accidentally by using '>' rather than '>>' 2) logs are automatically cleaned up by logrotate.

The following functions allow you to mark the start and end of a section of /var/log/user.log.

startlog() { export LOGMARK=$(date +%Y.%m.%d_%H:%M:%S); echo "$LOGMARK.START" | logger -t $USER; }


endlog() { echo "$LOGMARK.END" | logger -t $USER; }

printlog will print all lines between $LOGMARK.START and $LOGMARK.END, removing everything that is prepended to each line by logger.

printlog() { sudo sed -n -e "/$LOGMARK.START/,/$LOGMARK.END/p" /var/log/user.log| sed "s/.*$USER: //"; }

The following command should dump just about all the information that you could possibly want about your linux configuration into the clipboard.

startlog; for cmd in 'uname -a' 'cat /etc/issue' 'dmesg' 'lsusb' 'lspci' 'sudo lshw' 'lsmod'; do log $cmd; done; endlog; printlog | xsel --clipboard

This is ready for a trip to http://pastebin.com/, and you don't have to worry about leaving temporary files lying around cluttering up $HOME.

Caveats: I'm sure that startlog, endlog, and printlog could use some cleanup and error checking... there are unchecked dependencies between printlog and endlog, as well as between endlog and startlog.

It might be useful for 'log' to send stderr to logger as well.

dd [...] p
2010-07-23 23:19:06
User: bartonski
Functions: dd

Use this if you're using vi editing mode.

Example use :

sudo vim /root/bin/ ##uh... autocomplete doesn't work... dd sudo ls /root/bin

##ah! that's the name of the file!

<p> sudo vim /root/bin/ ##resume here! Thanks readline!
perltidy foo.pl
2010-07-19 11:51:47
User: bartonski

By default, perltidy will create a file with the extension '.tdy'.

fdiff() { ${DIFFCMD:-diff} <( $1 $2 ) <( $1 $3 ); }
2010-07-16 13:41:00
User: bartonski

Fdiff will run the command given by the first argument against the input files given as the second and third arguments, and diff the results.

It will use 'diff' as the default diff program, but this can be changed by setting $DIFFCMD, e.g.

export DIFFCMD=vimdiff; fdiff zcat 0716_0020005.raw.gz 0716_0030005.raw.gz


This function will work under bash, but requires the use of command substitution, which is not available under a strict ANSI shell.

comment() { echo "" > /dev/null; }
2010-05-03 16:14:04
User: bartonski

A null operation with the name 'comment', allowing comments to be written to HISTFILE. Prepending '#' to a command will *not* write the command to the history file, although it will be available for the current session, thus '#' is not useful for keeping track of comments past the current session.

2010-04-04 16:34:45
User: bartonski

the '!' command in vi spawns a shell, then pipes all of the specified lines in the buffer through the command specified after '!', replacing all input lines with the result of the command.

<esc> q a ...vim commands... <esc> q (to record macro) @a (plays macro 'a').
2010-04-02 04:33:36
User: bartonski

You can record, then replay a series of keystrokes in vim. In command mode 'q', then a letter [a-zA-Z] starts macro recording mode. Enter a series of vim commands. When done, enter command mode again, and press 'q' to stop recording.

To replay, enter command mode, then press @{letter}

2010-03-26 15:01:34
User: bartonski

While editing a source file in vim, or using vimdiff to compare two or more files, the ':TOhtml' command can be used to export each buffer as an html file, including syntax highlighting and vimdiff colorization. If you are in insert mode in vim, you will have to type


This will open a new buffer filled with html, which you can then save.