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.

Universal configuration monitoring and system of record for IT.

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



Psst. Open beta.

Wow, didn't really expect you to read this far down. The latest iteration of the site is in open beta. It's a gentle open beta-- not in prime-time just yet. It's being hosted over at UpGuard (link) and you are more than welcome to give it a shot. Couple things:

  • » The open beta is running a copy of the database that will not carry over to the final version. Don't post anything you don't mind losing.
  • » If you wish to use your user account, you will probably need to reset your password.
Your feedback is appreciated via the form on the beta page. Thanks! -Jon & CLFU Team

Commands using read from sorted by
Terminal - Commands using read - 304 results
find . -name "*.jar" | while read line; do echo "### $line "; unzip -l $line; done | grep "^###\|you-string" |less
find . -name "*.jar" | while read line; do unzip -l $line; done | grep your-string
xargsb() { while read -r cmd; do ${@//'{}'/$cmd}; done; }
2010-09-28 06:35:39
User: BobbyTables
Functions: read

Similar to xargs -i, but works with builtin bash commands (rather than running "bash -c ..." through xargs)

echo "12 morning\n15 afternoon\n24 evening" |while read t g; do if [ `date +%H` -lt $t ]; then echo "Good $g"; break; fi; done
package=$1; list=/var/lib/dpkg/info/${package}.list; inst=$(stat "$list" -c %X); cat $list | (while read file; do if [ -f "$file" ];then acc=$(stat "$file" -c %X); if [ $inst -lt $acc ]; then echo used $file; exit 0; fi; fi; done; exit 1)
2010-09-20 18:10:19
User: pipeliner
Functions: cat echo exit read stat
Tags: apt dpkg date stat

This script compares the modification date of /var/lib/dpkg/info/${package}.list and all the files mentioned there.

It could be wrong on noatime partitions.

Here is non-oneliner:




inst=$(stat "$list" -c %X);

cat $list |


while read file; do

if [ -f "$file" ]; then

acc=$(stat "$file" -c %X);

if [ $inst -lt $acc ]; then

echo used $file

exit 0




exit 1


cowsay -l | sed '1d;s/ /\n/g' | while read f; do cowsay -f $f $f;done
read -e -s -p "Password: " password
2010-08-18 17:53:27
User: freiheit
Functions: read
wget --user=username --password="$password" http://example.org/

Instead of hiding commands entirely from history, I prefer to use "read" to put the password into a variable, and then use that variable in the commands instead of the password. Without the "-e" and "-s" it should work in any bourne-type shell, but the -s is what makes sure the password doesn't get echoed to the screen at all. (-e makes editing work a bit better)

find . -type f -iname '*.flac' | while read FILE; do FILENAME="${FILE%.*}"; flac -cd "$FILE" | lame -b 192 - "${FILENAME}.mp3"; done
2010-08-15 19:02:19
User: paulochf
Functions: find read

find . -type f -iname '*.flac' # searches from the current folder recursively for .flac audio files

| # the output (a .flac audio files with relative path from ./ ) is piped to

while read FILE; do FILENAME="${FILE%.*}"; flac -cd "$FILE" | lame -b 192 - "${FILENAME}.mp3"; done

# for each line on the list:

# FILE gets the file with .flac extension and relative path

# FILENAME gets FILE without the .flac extension

# run flac for that FILE with output piped to lame conversion to mp3 using 192Kb bitrate

ls | while read -r FILE; do mv -v "$FILE" `echo "prependtext$FILE" `; done
2010-08-14 14:19:18
User: IgnitionWeb
Functions: ls mv read
Tags: echo mv prepen

Prepends all directory items with "prependtext"

ls | while read -r FILE; do mv -v "$FILE" `echo $FILE | tr -d ' '`; done
2010-08-14 14:10:48
User: IgnitionWeb
Functions: ls mv read tr
Tags: space echo while tr

all files in the directory get moved, in doing so the new name of the file is the original name with out spaces (using translate command)

find <dir> -name "<pattern>" | while read file; do echo -n .; output=$(<command>) || (echo ; echo $file:; echo "$output"; ); done
2010-08-10 11:45:31
User: Marco
Functions: echo find read

This is a command template for achiving the following:

* loop over files --> find -name "" | while read file; do ...; done

* output progress --> echo -n .

* execute some command on each file and save output for later usage --> output=$()

* if command failed, open subshell and echo newline --> || (echo;...;...;)

* echo output of command --> echo "$output"

find -name 'foo*' | while read i; do echo "$i"; done
2010-07-16 15:35:27
User: imgx64
Functions: echo find read

Replace the echo command with whatever commands you want.

'read' reads a line from stdin and places the text in the variable, the stdin of the while loop comes from the find command.

Note that with simple commands, an easier way is using the '-exec' option of find. My command is useful if you want to execute multiple commands in the loop.

read -p "enter url:" a ; w3m -dump $a > /dev/shm/e1q ; less /dev/shm/e1q ; read -p "save file as text (y/n)?" b ; if [ $b = "y" ] ; then read -p "enter path with filename:" c && touch $(eval echo "$c") ; mv /dev/shm/e1q $(eval echo "$c") ; fi ; echo DONE
2010-07-13 22:36:38
User: LinuxMan
Functions: c++ echo eval less mv read touch

Thanks th John_W for suggesting the fix allowing ~/ to be used when saving a directory.


Type in a url, it will show a preview of what the file will look like when saved, then asks if you want to save the preview and where you want to save it. Great for grabbing the latest commandlinefu commands without a full web browser or even a GUI. Requires: w3m

while read col1 col23; do echo $col1; done < three-column.txt > first-column.txt
while read l; do echo ${l%% *}; done < three-column-list.txt > only-first-column.txt
2010-07-09 03:42:56
User: zed
Functions: echo read

The above is an example of grabbing only the first column. You can define the start and end points specifically by chacater position using the following command:

while read l; do echo ${l:10:40}; done < three-column-list.txt > column-c10-c40.txt

Of course, it doesn't have to be a column, or extraction, it can be replacement

while read l; do echo ${l/foo/bar}; done < list-with-foo.txt > list-with-bar.txt

Read more about parameter expansion here:


Think of this as an alternative to awk or sed for file operations

wmctrl -l -p | while read line; do ps -o cmd= "$(echo "$line" | awk '$0=$3')"; done > ~/.windows
2010-07-04 22:11:24
User: matthewbauer
Functions: ps read

This will save your open windows to a file (~/.windows).

To start those applications:

cat ~/.windows | while read line; do $line &; done

Should work on any EWMH/NetWM compatible X Window Manager.

If you use DWM or another Window Manager not using EWMH or NetWM try this:

xwininfo -root -children | grep '^ ' | grep -v children | grep -v '<unknown>' | sed -n 's/^ *\(0x[0-9a-f]*\) .*/\1/p' | uniq | while read line; do xprop -id $line _NET_WM_PID | sed -n 's/.* = \([0-9]*\)$/\1/p'; done | uniq -u | grep -v '^$' | while read line; do ps -o cmd= $line; done > ~/.windows
emerge -av1 `qlist --installed --nocolor | uniq | while read cp; do qlist --exact $cp | while read file; do test -e $file || { echo $cp; echo "$cp: missing $file (and maybe more)" 1>&2; break; }; done; done`
2010-07-04 19:55:42
User: Flameeyes
Functions: echo read test uniq

Revised approach to and3k's version, using pipes and read rather than command substitution. This does not require fiddling with IFS when paths have whitespace, and does not risk hitting command-line size limits.

It's less verbose on the missing files, but it stops iterating at the first file that's missing, so it should be definitely faster.

I expanded all the qlist options to be more self-describing.

statt(){ C=c;stat --h|sed '/Th/,/NO/!d;/%/!d'|while read l;do p=${l/% */};[ $p == %Z ]&&C=fc&&echo ^FS:^;echo "`stat -$C $p \"$1\"` ^$p^${l#%* }";done|column -ts^; }
2010-06-11 23:31:03
User: AskApache
Functions: column read sed

This shows every bit of information that stat can get for any file, dir, fifo, etc. It's great because it also shows the format and explains it for each format option.

If you just want stat help, create this handy alias 'stath' to display all format options with explanations.

alias stath="stat --h|sed '/Th/,/NO/!d;/%/!d'"

To display on 2 lines:

( F=/etc/screenrc N=c IFS=$'\n'; for L in $(sed 's/%Z./%Z\n/'<<<`stat --h|sed -n '/^ *%/s/^ *%\(.\).*$/\1:%\1/p'`); do G=$(echo "stat -$N '$L' \"$F\""); eval $G; N=fc;done; )

For a similarly powerful stat-like function optimized for pretty output (and can sort by any field), check out the "lll" function


From my .bash_profile ->


sortwc () { local L;while read -r L;do builtin printf "${#L}@%s\n" "$L";done|sort -n|sed -u 's/^[^@]*@//'; }
2010-05-20 20:13:52
User: AskApache
Functions: printf read sed sort

This provides a way to sort output based on the length of the line, so that shorter lines appear before longer lines. It's an addon to the sort that I've wanted for years, sometimes it's very useful. Taken from my http://www.askapache.com/linux-unix/bash_profile-functions-advanced-shell.html

mplayer http://minnesota.publicradio.org/tools/play/streams/the_current.pls < /dev/null | grep --line-buffered "StreamTitle='.*S" -o | grep --line-buffered "'.*'" -o > mus & tail -n0 -f mus | while read line; do notify-send "Music Change" "$line";done
2010-05-09 17:51:40
User: spiffwalker
Functions: grep read tail

Plays the mp3 stream of The Current as a background job. When you are done run:

fg %1

then to exit

Quite possible with Growl for mac I'd guess, although have not tried.

Libnotify needed for notification, stream will still work otherwise

echo 'Host or [email protected]?:'; read newserver && ssh-keygen -N "" -t rsa -f ~/.ssh/id_rsa ; ssh $newserver cat <~/.ssh/id_rsa.pub ">>" ~/.ssh/authorized_keys ; ssh $newserver
2010-05-07 06:24:53
User: alf
Functions: cat echo read ssh ssh-keygen
Tags: ssh ssh-keygen

Some servers don't have ssh-copy-id, this works in those cases.

It will ask for the destination server, this can be IP, hostname, or [email protected] if different from current user.

Ssh keygen will let you know if a pubkey already exists on your system and you can opt to not overwrite it.

grep -ioE "(url\(|src=)['\"]?[^)'\"]*" a.html | grep -ioE "[^\"'(]*.(jpg|png|gif)" | while read l ; do sed -i "s>$l>data:image/${l/[^.]*./};base64,`openssl enc -base64 -in $l| tr -d '\n'`>" a.html ; done;
2010-05-05 14:07:51
User: zhangweiwu
Functions: grep read sed
Tags: html

in "a.html", find all images referred as relative URI in an HTML file by "src" attribute of "img" element, replace them with "data:" URI. This useful to create single HTML file holding all images in it, as a replacement of the IE-created .mht file format. The generated HTML works fine on every other browser except IE, as well as many HTML editors like kompozer, while the .mht format only works for IE, but not for every other browser. Compare to the KDE's own single-file-web-page format "war" format, which only opens correctly on KDE, the HTML file with "data:" URI is more universally supported.

The above command have many bugs. My commandline-fu is too limited to fix them:

1. it assume all URLs are relative URIs, thus works in this case:

<img src="images/logo.png"/>

but does not work in this case:

<img src="http://www.my_web_site.com/images/logo.png" />

This may not be a bug, as full URIs perhaps should be ignored in many use cases.

2. it only work for images whoes file name suffix is one of .jpg, .gif, .png, albeit images with .jpeg suffix and those without extension names at all are legal to HTML.

3. image file name is not allowed to contain "(" even though frequently used, as in "(copy of) my car.jpg". Besides, neither single nor double quotes are allowed.

4. There is infact a big flaw in this, file names are actually used as regular expression to be replaced with base64 encoded content. This cause the script to fail in many other cases. Example: 'D:\images\logo.png', where backward slash have different meaning in regular expression. I don't know how to fix this. I don't know any command that can do full text (no regular expression) replacement the way basic editors like gedit does.

5. The original a.html are not preserved, so a user should make a copy first in case things go wrong.

cat list|while read lines;do echo "USER admin">ftp;echo "PASS $lines">>ftp;echo "QUIT">>ftp;nc 21 <ftp>ftp2;echo "trying: $lines";cat ftp2|grep "230">/dev/null;[ "$?" -eq "0" ]&& echo "pass: $lines" && break;done
cat domainlist.txt | while read line; do echo -ne $line; whois $line | grep Expiration ; done | sed 's:Expiration Date::'
2010-05-02 06:49:09
User: netsaint
Functions: cat echo grep read sed whois

Create a text file called domainlist.txt with a domain per line, then run the command above. All registries are a little different, so play around with the command. Should produce a list of domains and their expirations date. I am responsible for my companies domains and have a dozen or so myself, so this is a quick check if I overlooked any.

find ~ -maxdepth 2 -name .git -print | while read repo; do cd $(dirname $repo); git pull; done