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.


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:



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.




Commands tagged bash from sorted by
Terminal - Commands tagged bash - 694 results
command <<< word
2012-02-29 03:14:54
Functions: command
Tags: bash stdin

Don't do this:

echo word | command

Using a bash "here strings" and "here documents" look leeter than piping echo into the command. Also prevents subshell execution. Word is also expanded as usual.

find . -depth -name '* *' -execdir bash \-c 'a="{}";mv -f "$a" ${a// /_}' \;
2012-02-28 04:03:40
User: DewiMorgan
Functions: bash find mv

Sometimes, you don't want to just replace the spaces in the current folder, but through the whole folder tree - such as your whole music collection, perhaps. Or maybe you want to do some other renaming operation throughout a tree - this command's useful for that, too.

To rename stuff through a whole directory tree, you might expect this to work:

for a in `find . -name '* *'`;do mv -i "$a" ${a// /_};done

No such luck. The "for" command will split its parameters on spaces unless the spaces are escaped, so given a file "foo bar", the above would not try to move the file "foo bar" to "foo_bar" but rather the file "foo" to "foo", and the file "bar" to "bar". Instead, find's -execdir and -depth arguments need to be used, to set a variable to the filename, and rename files within the directory before we rename the directory.

It has to be -execdir and won't work with just -exec - that would try to rename "foo bar/baz quux" to "foo_bar/baz_quux" in one step, rather than going into "foo bar/", changing "baz quux" to "baz_quux", then stepping out and changing "foo bar/" into "foo_bar/".

To rename just files, or just directories, you can put "-type f" or "-type d" after the "-depth" param.

You could probably safely replace the "mv" part of the line with a "rename" command, like rename 'y/ /_/' *, but I haven't tried, since that's way less portable.

for ((x=0;;x+=5)); do sleep 5; espeak $x & done
2012-02-22 00:26:57
Functions: sleep
Tags: audio bash timer

Useful contexts :

You are doing yoga or some other physical training in which you are holding a position.

Or you practice the pomodoro productivity technique.

Or your girlfriend said "We're leaving in 40 minutes".

Design details:

sleep executes before espeak to give you a 5 seconds head start.

espeak is run in the background so it doesn't mess up the timing.

testt(){ o=abcdefghLkprsStuwxOGN;echo $@;for((i=0;i<${#o};i++));do c=${o:$i:1};test -$c $1 && help test | sed "/^ *-$c/!d;1q;s/^[^T]*/-$c /;s/ if/ -/";done; }
2012-02-21 16:54:53
User: AskApache
Functions: echo sed test

Applies each file operator using the built-in test.

testt /home/askapache/.sq


-a True - file exists.

-d True - file is a directory.

-e True - file exists.

-r True - file is readable by you.

-s True - file exists and is not empty.

-w True - the file is writable by you.

-x True - the file is executable by you.

-O True - the file is effectively owned by you.

-G True - the file is effectively owned by your group.

-N True - the file has been modified since it was last read.

Full Function:

testt ()


local dp;

until [ -z "${1:-}" ]; do


[[ ! -a "$1" ]] && dp="$PWD/$dp";

command ls -w $((${COLUMNS:-80}-20)) -lA --color=tty -d "$dp";

[[ -d "$dp" ]] && find "$dp" -mount -depth -wholename "$dp" -printf '%.5m %10M %#15s %#9u %-9g %#5U %-5G %Am/%Ad/%AY %Cm/%Cd/%CY %Tm/%Td/%TY [%Y] %p\n' -a -quit 2> /dev/null;

for f in a b c d e f g h L k p r s S t u w x O G N;


test -$f "$dp" && help test | sed "/-$f F/!d" | sed -e 's#^[\t ]*-\([a-zA-Z]\{1\}\) F[A-Z]*[\t ]* True if#-\1 "'$dp'" #g';





grep $'\t' sample.txt
cmdfu(){ local t=~/cmdfu;echo -e "\n# $1 {{{1">>$t;curl -s "commandlinefu.com/commands/matching/$1/`echo -n $1|base64`/plaintext"|sed '1,2d;s/^#.*/& {{{2/g'>$t;vim -u /dev/null -c "set ft=sh fdm=marker fdl=1 noswf" -M $t;rm $t; }
2012-02-21 05:43:16
User: AskApache
Functions: echo rm sed vim

Here is the full function (got trunctated), which is much better and works for multiple queries.

function cmdfu () {

local t=~/cmdfu;

until [[ -z $1 ]]; do

echo -e "\n# $1 {{{1" >> $t;

curl -s "commandlinefu.com/commands/matching/$1/`echo -n $1|base64`/plaintext" | sed '1,2d;s/^#.*/& {{{2/g' | tee -a $t > $t.c;

sed -i "s/^# $1 {/# $1 - `grep -c '^#' $t.c` {/" $t;



vim -u /dev/null -c "set ft=sh fdm=marker fdl=1 noswf" -M $t;

rm $t $t.c


Searches commandlinefu for single/multiple queries and displays syntax-highlighted, folded, and numbered results in vim.

mtr google.com
2012-02-19 22:27:48
User: d_voge

You need to have mtr installed on your host.

for i in {1..30}; do ping -t $i -c 1 google.com; done | grep "Time to live exceeded"
2012-02-19 13:37:04
User: fossilet
Functions: grep ping

This command uses ping to get the routers' IP addresses to the destination host as traceroute does. If you know what I mean..

sed -e 's/[;|][[:space:]]*/\n/g' .bash_history | cut --delimiter=' ' --fields=1 | sort | uniq --count | sort --numeric-sort --reverse | head --lines=20
regenerateCSR () { openssl genrsa -out $2 2048; openssl x509 -x509toreq -in $1 -out $3 -signkey $2; }
echo -n '#!'$(which awk)
sudo curl "http://hg.mindrot.org/openssh/raw-file/c746d1a70cfa/contrib/ssh-copy-id" -o /usr/bin/ssh-copy-id && sudo chmod 755 /usr/bin/ssh-copy-id
2012-02-09 20:29:24
User: misterich
Functions: chmod sudo

Mac install ssh-copy-id

From there on out, you would upload keys to a server like this:

(make sure to double quote the full path to your key)

ssh-copy-id -i "/PATH/TO/YOUR/PRIVATE/KEY" username@server

or, if your SSH server uses a different port (often, they will require that the port be '2222' or some other nonsense:

(note the double quotes on *both* the "/path/to/key" and "user@server -pXXXX"):

ssh-copy-id -i "/PATH/TO/YOUR/PRIVATE/KEY" "username@server -pXXXX"

...where XXXX is the ssh port on that server

echo -n "IP Address or Machine Name: "; read IP; ping -c 1 -q $IP >/dev/null 2>&1 && echo -e "\e[00;32mOnline\e[00m" || echo -e "\e[00;31mOffline\e[00m"
2012-02-09 07:00:03
User: crlf
Functions: echo ping read
Tags: bash echo IP ping

I have used single packet, and in a silent mode with no display of ping stats. This is with color and UI improvement to the http://www.commandlinefu.com/commands/view/10220/check-if-a-machine-is-online. It is as per the enhancements suggested.

:autocmd BufNewFile *.sh,*.bash 0put =\"#!/bin/bash\<nl># -*- coding: UTF8 -*-\<nl>\<nl>\"|$
2012-02-06 08:28:05
User: jlaunay
Tags: bash

or add this line to your ~/.vimrc if using vim

echo '#!'$(which bash) > script.sh
2012-02-06 08:25:27
User: sharfah
Functions: echo which
Tags: bash

Writes out the shebang line (#!/bin/bash) to the script.

{ echo -n '#!'; which bash; } > script.sh
sed -i 6,66d <filename>
2012-02-04 02:29:40
User: icsamples
Functions: sed
Tags: bash sed

Delete range of lines. Ex: Line 6 through 66 in .

sed -i <file> -re '<start>,<end>d'
sed -i <start>,<end>d <filename>
perl -i -ne 'print if $. == 3..5' <filename>
vi +'<start>,<end>d' +wq <filename>
2012-01-27 02:50:01
User: captaincomic
Tags: bash

For example

path="/etc/apt/sources.list"; echo ${path//'/'/'\/'}

will print

vi +START,ENDd +wq sample.txt
2012-01-26 20:47:35
User: titan2x
Functions: vi
Tags: bash vi

Deletes lines from START to END, inclusive. For example +4,10d will delete line 4, 5, ..., 10. Just like the vi command :4,10d does it.

vi +{<end>..<start>}d +wq <filename>
2012-01-26 20:36:04
User: javidjamae
Functions: vi
Tags: bash vi

Deletes lines to of a file. You must put the end line first in the range for the curly brace expansion, otherwise it will not work properly.

for FILE in `ls -1`; do if [ -L "$FILE" ]; then cp $(readlink "$FILE") ${FILE}_rf; rm -f $FILE; mv ${FILE}_rf "$FILE"; fi; done