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
ls|grep .mp3 >list.txt; while read line; do newname=`echo $line|sed 's/\ /-/g'|sort`; newname=`echo $newname|tr -s '-' `; echo $newname; echo $newname>> tracklist.txt;mv "$line" "$newname"; done <list.txt; rm list.txt
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.

fdupes -R -1 path | while read -r line; do (echo $line | xargs -n 1 | (first="true"; firstfile=""; while read file; do if [ "$first" == "true" ]; then first="false"; firstfile=$file; else ln --force "$firstfile" "$file"; fi; done)); done
2012-02-01 15:08:18
User: eclewis
Functions: echo ln read xargs

This variation can handle file paths containing spaces.

fdupes -r -1 Neu | while read line; do j="0"; buf=""; for file in ${line[*]}; do if [ "$j" == "0" ]; then j="1"; buf=$file; else ln -f $buf $file; fi; done; done
for fn in xkcd*.png xkcd*.jpg; do echo $fn; read xw xh <<<$(identify -format '%w %h' $fn); nn="$(echo $fn | sed 's/xkcd-\([^-]\+\)-.*/\1/')"; wget -q -O xkcd-${nn}.json http://xkcd.com/$nn/info.0.json; tt="$(sed 's/.*"title": "\([^"]\+\)",.*/\1/' ...
2012-01-06 20:26:11
User: fpunktk
Functions: echo read wget

full command:

for fn in xkcd*.png xkcd*.jpg; do; echo $fn; read xw xh <<<$(identify -format '%w %h' $fn); nn="$(echo $fn | sed 's/xkcd-\([0-9]\+\)-.*/\1/')"; wget -q -O xkcd-${nn}.json http://xkcd.com/$nn/info.0.json; tt="$(sed 's/.*"title": "\([^"]*\)", .*/\1/' xkcd-${nn}.json)"; at="$(sed 's/.*alt": "\(.*\)", .*/\1/' xkcd-${nn}.json)"; convert -background white -fill black -font /usr/share/fonts/truetype/freefont/FreeSansBold.ttf -pointsize 26 -size ${xw}x -gravity Center caption:"$tt" tt.png; convert -background '#FFF9BD' -border 1x1 -bordercolor black -fill black -font /usr/share/fonts/truetype/freefont/FreeSans.ttf -pointsize 16 -size $(($xw - 2))x -gravity Center caption:"$at" at.png; th=$(identify -format '%h' tt.png); ah=$(identify -format '%h' at.png); convert -size ${xw}x$(($xh+$th+$ah+5)) "xc:white" tt.png -geometry +0+0 -composite $fn -geometry +0+$th -composite at.png -geometry +0+$(($th+$xh+5)) -composite ${fn%\.*}_cmp.png; echo -e "$fn $nn $xw $xh $th $ah \n$tt \n$at\n"; done

this assumes that all comics are saved as xkcd-[number]-[title].{png|jpg}.

it will then download the title and alt-text, create pictures from them, and put everything together in a new png-file.

it's not perfect, but it worked for nearly all my comics.

it uses the xkcd-json-interface.

though it's poorly written, it doesn't completely break on http://xkcd.com/859/

vgdisplay -v 2>/dev/null | grep "^ LV Name" | while read A B LVDEV; do echo $LVDEV; done
while read l; do echo -e "$RANDOM\t$l"; done | sort -n | cut -f 2
c="cp -a";e="~";echo -e "\npaste\n";i=0;k="1"; while [[ "$k" != "" ]]; do read -a k;r[i]=$k;((i++));done;i=0;while :;do t=${r[i]};[ "$t" == "" ] && break; g=$(echo $c ${r[i]} $e);echo -e $g "\ny/n?";read y;[ "$y" != "n" ] && eval $g;((i++));done
2011-12-04 12:45:44
User: knoppix5
Functions: echo eval read


command [options] [paste your variable here] parameter

command [options] [paste entire column of variables here] parameter


(hard-code command "c" and parameter "e" according to your wishes: in example shown command = "cp -a" and parameter = "~")


- Quick exchange only variable part of a long command line

- Make variable part to be an entire column of data (i.e. file list)

- Full control while processing every single item


Paste column of data from anywhere. I.e. utilize the Block Select Mode to drag, select and copy columns (In KDE Konsole with Ctrl+Alt pressed, or only Ctrl pressed in GNOME Terminal respectively).


You can paste only one single variable in a row. If there are more space separated variables in a row only first one will be processed, but you can arrange your variables in a column instead. To transpose rows to columns or vice versa look at Linux manual pages for 'cut' and 'paste'.


- add edit mode to vary command "c" and parameter "e" on the fly

- add one edit mode more to handle every list item different

- add y/n/a (=All) instead of only y(=default)/n to allowed answers


The code is not optimized, only the basic idea is presented here. It's up to you to shorten code or extend the functionality.

read -s PASS; echo $PASS | convert sensitive.jpg -encipher - -depth 8 png24:hidden.png
2011-11-25 18:15:23
User: kev
Functions: echo read
Tags: ImageMagick

Do not use JPEG, GIF, or any other 'lossy' image encoding with Encryption

read -s pass; echo $pass | md5sum | base64 | cut -c -16
2011-11-24 20:23:47
User: bugmenot
Functions: cut echo md5sum read

Why remember? Generate!

Up to 48 chars, works on any unix-like system (NB: BSD use md5 instead of md5sum)

read c; while [ -n "$c" ]; do clear; echo -e "$c = "$(echo "$c" |bc -l)"\n"; read c; done
read -d ""
2011-10-25 18:44:11
User: totti
Functions: read

Handle any bad named file which contains ",',\n,\b,\t,` etc

Store the file name as null character separated list

find . -print0 >name.lst

and retrieve it using

read -r -d ""


find . -print0 >name.lst; cat name.lst| while IFS="" read -r -d "" file; do ls -l "$file"; done
while read line; do echo $line; done <<< "$var"
2011-09-22 16:53:32
User: totti
Functions: echo read

Consider the following simple situation [ reading something using while and read ]

[See script 1 in sample output]


The variable var is assigned with "nullll" at first. Inside the while loop [piped while] it is assigned with "whillleeee". [Onlly 2 assignments stmts]. Outside the loop the last assigned value for "var" [and no variable] inside the while can't be accessed [Due to pipe, var is executed in a sub shell].

In these type of situation variables can be accessed by modifying as follows.

[See script 2 in sample output]


Vary helpful when reading a set of items, say file names, stored on a file [or variable] to an array an use it later.

Is there any other way 2 access variables inside and outside the loop ??

find . -printf "%T@ %p\n" | sed -e 1d | while read ts fn; do ts=${ts%.*}; if [ $ts -ge ${gts:-0} ]; then gts=$ts; echo `date -d @$gts` $fn; fi; done
read -ra words <<< "<sentence>" && echo "${words[@]^}"
param=${param:-$(read -p "Enter parameter: "; echo "$REPLY")}
2011-09-08 20:48:31
User: frans
Functions: echo read

Can be used for command line parameters too.

If you have a more complicated way of entering values (validation, GUI, ...), then write a function i.e. EnterValue() that echoes the value and then you can write:

ping HOSTNAME | while read pong; do echo "$(date): $pong"; done
get_duration () { IFS=.: read -r _ h m s _ < <(ffmpeg -i "$1" 2>&1 | grep Duration);echo $(( h * 3600 + m * 60 + s )); }
SCALE=3; WIDTHL=10; WIDTHR=60; BAR="12345678"; BAR="${BAR//?/==========}"; while read LEFT RIGHT rest ; do RIGHT=$((RIGHT/SCALE)); printf "%${WIDTHL}s: %-${WIDTHR}s\n" "${LEFT:0:$WIDTHL}" "|${BAR:0:$RIGHT}*"; done < dataset.dat
2011-08-22 19:35:21
User: andreasS
Functions: printf read

WIDTHL=10 and WIDTHR=60 are setting the widths of the left and the right column/bar. BAR="12345678" etc. is used to create a 80 char long string of "="s. I didn't know any shorter way.

If you want to pipe results into it, wrap the whole thing in ( ... )

I know that printing bar graphs can be done rather easily by other means. Here, I was looking for a Bash only variant.

while IFS= read -r -u3 -d $'\0' file; do file "$file" | egrep -q 'executable|ELF' && chmod +x "$file"; done 3< <(find . -type f -print0)
2011-08-18 15:37:23
User: keymon
Functions: chmod egrep file find read

If you make a mess (like I did) and you removed all the executable permissions of a directory (or you set executable permissions to everything) this can help.

It supports spaces and other special characters in the file paths, but it will work only in bash, GNU find and GNU egrep.

You can complement it with these two commands:

1. add executable permission to directories:

find . type d -print0 | xargs -0 chmod +x

2. and remove to files:

find . type d -print0 | xargs -0 chmod -x

Or, in the same loop:

while IFS= read -r -u3 -d $'\0' file; do case $(file "$file" | cut -f 2- -d :) in :*executable*|*ELF*|*directory*) chmod +x "$file" ;; *) chmod -x "$file" ;; esac || break done 3< <(find . -print0)

Ideas stolen from Greg's wiki: http://mywiki.wooledge.org/BashFAQ/020

git branch | cut -c3- | grep -v "^master$" | while read line; do git branch -d $line; done | grep 'Deleted branch' | awk '{print $3;}' | while read line; do git push <target_remote> :$line; done
2011-08-13 16:58:34
User: gocoogs
Functions: awk cut grep read

attempts to delete all local branches. git will fail on any branches not fully merged into local master, so don't worry about losing work. git will return the names of any successfully deleted branches. Find those in the output with grep, then push null repositories to the corresponding names to your target remote.


- your local and remote branches are identically named, and there's nothing extra in the remote branch that you still want

- EDIT: you want to keep your local master branch

find . -type l | (while read FN ; do test -e "$FN" || ls -ld "$FN"; done)
read day month year < <(date +'%d %m %y')
2011-07-30 06:06:29
User: frans
Functions: date read
Tags: bash read

No command substitution but subshell redirection

read day month year <<< $(date +'%d %m %y')
read VAR1 VAR2 VAR3 <<< aa bb cc; echo $VAR2