We aim to collect practical, well-explained bash one-liners, and promote best practices in shell scripting. To get the latest bash one-liners, follow @bashoneliners on Twitter, or subscribe to our rss feed. If you find any problems, report a bug on GitHub.



Record audio from microphone or sound input from the console

 $ sox -t ossdsp -w -s -r 44100 -c 2 /dev/dsp -t raw - | lame -x -m s - File.mp3

— by Kleper on July 28, 2012, 8:55 p.m.


sox is software that lets you connect directly to the sound card and send what passes for it in raw format and the system memory through the concatenation of the linux command we can make real-time audio processing is generated by licks and be converted to mp3

Need plugin for alsa oss to run on modern distributions.


Use vim to pretty-print code with syntax highlighting

 $ vim +'hardcopy > output.ps' +q style.css 

— by openiduser3 on July 21, 2012, 12:13 a.m.


If you have syntax highlighting properly setup in vim, this command will pretty-print the specified file with syntax highlighting to output.ps.

If you prefer PDF, you can convert using ps2pdf output.ps.


Monitors and generates log, about the files received via ftp, and also verifies the existence of the file

 $ for i in $(cat /var/log/vsftpd.log | grep $DATE_TIME | grep UPLOAD | grep OK); do ls /FTP/HOME/$i >> /dev/null 2> \&1; if \[ $? = 0 \]; then echo "$i" >> $FILES_OK_UPLOADS.log; else  echo "$DATE ERROR: File $i not found" >> $FTP_FILES_NOTOK_$DATE_TIME.log; fi; done

— by dark_axl on July 10, 2012, 8:54 p.m.


This one-liner checks and validates the received files via ftp, and generates a log of these files. To have a record of files received and be able to process, based on the successful transfer and the existence of the files.


Edit the Gimp launcher file to disable the splash screen

 $ printf '%s\n' ',s/^Exec=[^ ]*/& -s/' w q | ed /usr/share/applications/gimp.desktop

— by Anon8yhYNaVe on July 1, 2012, 12:57 a.m.


sed is designed for editing streams - editing files is what ed is for! You can get consistent behavior on any UNIX platform with the above one-liner.

The printf command sends a series of editing commands to ed, each separated by a newline. In this case, the substitution command ,s/^Exec=[^ ]*/& -s/ is nearly the same as in sed, appending a space and a -s to the line starting with Exec=. The only difference is the comma at the beginning designating the lines to operate on. This is shorthand for 1,$, which tells ed to apply the command to the first through the last lines (i.e., the entire file). w tells ed to write the file, and q to quit.


Edit the Gimp launcher file to disable the splash screen

 $ sudo sed -i 's/^Exec=[^ ]*/& -s/' /usr/share/applications/gimp.desktop

— by openiduser3 on June 30, 2012, 9:06 p.m.


  • The -i flag of sed means to perform the command "in place", that is, save any changes in the input file. Use this flag with extreme caution, one wrong move and you can completely break the original file.
  • The regex pattern /^Exec=[^ ]*/ will match the line starting with Exec= followed by zero or more non-space characters.
  • In the replacement string, & -s, the & is replaced with whatever was matched, in this example probably something like Exec=gimp-2.8, after which we add a space and the -s flag which will effectively disable the splash screen when starting Gimp.


The -i flag of sed works differently in GNU and BSD systems. This example works in GNU systems only. The equivalent in BSD is:

sudo sed -i '' 's/^Exec=[^ ]*/& -s/' /usr/share/applications/gimp.desktop

In any case, always be very careful when using the -i flag of sed.


`less` is more convenient with the `-F` flag

 $ less -F FILE1

— by openiduser3 on June 25, 2012, 6:47 p.m.


less is a "pager" program like more, with a lot of added features. By default, to exit less you have to press q. This can be annoying when viewing a small file that would fit on the screen.

The -F flag to the rescue! When started with the -F flag, less will quit if the entire input (whether from stdin or a file) fits on a single screen.

It has no effect whatsoever for longer input, so it is safe to add an alias for this:

alias less='less -F'

Echo a fixed text, a blank line and tail one line from file to another file

 $ { echo some text; echo; tail -n1 /var/log/apache2/error.log; } >> /path/to/file

— by openiduser3 on June 22, 2012, 5:29 p.m.


All the standard output from all the commands between the braces will be redirected.


Echo a fixed text, a blank line and tail one line from file to another file

 $ echo -e "From: me\n\n$(tail -n1 /var/log/apache2/error.log)" >> file

— by kevin on June 21, 2012, 8:18 p.m.


  • -e option to echo makes it interpret '\n' as a newline
  • $(command) syntax runs a command, then uses its output in place


Should always work in bash. Other shells may need different syntax.


Run a local shell script on a remote server without copying it there

 $ ssh user@server bash < /path/to/local/script.sh

— by openiduser3 on June 21, 2012, 12:06 a.m.


Yes this is almost trivial: a simple input redirection, from a local shell script to be executed by bash on the remote server.

The important point being, if you have a complex and very long chain of commands to run on a remote server, it is better to put the commands in a shell script, break the long one-liner to multiple lines for readability and easier debugging.

Replace bash accordingly depending on the language of the script, for example for python:

ssh user@server python < /path/to/local/script.py

Convert a list of terms in slug format to capitalized words

 $ sed -e 's/^./\U&/' -e 's/_./\U&/g' -e 's/_/ /g' /path/to/input

— by openiduser3 on June 17, 2012, 7:54 a.m.


The goal here is to take an input like this:


... and convert it to an output like this:

Police Station
Post Office
Real Estate Agency
  • -e ... the sed command can take several -e parameters, which will be executed one by one when processing each line in the input
  • The s/// command is a pattern replacement, and has the general format s/pattern/replacement/flags
  • s/^./\U&/ - replace the first letter of the line with uppercase version of the letter: \U means convert to uppercase, & is the matched string
  • s/_./\U&/g- replace _ and any letter followed by it. The g flag at the end means a "global" replacement, so all occurrences of the pattern _. will be replaced
  • s/_/ /g - replace all underscores with spaces
  • Input to sed can come from a list of files, or input redirection with <, or from a pipe.

Execute different commands with find depending on file type

 $ find /path/to/dir -type d -exec chmod 0755 '{}' \; -o -type f -exec chmod 0644 '{}' \;

— by openiduser3 on June 17, 2012, 12:01 a.m.


  • -type d -exec chmod 0755 '{}' \; for each directory, run chmod 0755
  • \; is to mark the end of the -exec
  • {} is replaced with the filename, we enclosed it in single quotes like this '{}' to handle spaces in filenames
  • -ological OR operator
  • -type f -exec chmod 0644 '{}' \; for each regular file, run chmod 0644

Convert m4a files to mp3 using faad and lame

 $ faad -o tmp.wav music.m4a && lame -b 192 tmp.wav music.mp3

— by openiduser3 on June 14, 2012, 9:29 a.m.


  • Step 1: convert m4a to wav using faad
  • Step 2: convert wav to mp3 using lame
  • -b 192 is the bitrate


Neither faad nor lame are standard commands.


Write both stdout and stderr to the same file

 $ do_something.sh &> out.log

— by openiduser3 on June 5, 2012, 11:34 a.m.


Note: this is not always the same as:

do_something.sh >out.log 2>out.log

Using &> will ensure that the order of lines coming from stdout and stderr is preserved.


This works in /bin/bash and may not work in /bin/sh or other stripped down variants of bash.


Create or mount an encrypted directory using encfs

 $ encfs -i 5 $PWD/raw $PWD/content

— by openiduser3 on May 22, 2012, 12:21 a.m.


The first time you run this, it will create an encrypted directory raw in the current working directory, and mount it on directory content in the same directory. It will ask a couple of questions:

  1. Create directory "raw" ? -- answer "y"
  2. Create directory "content" ? -- answer "y"
  3. Choose configuration mode -- press enter, or "p" for "paranoia mode"

The content directory will be visible and editable only by your user, and all the files you put inside will be saved encrypted under raw. The encrypted data is only visible when raw is mounted somewhere.

The -i 5 means the content directory will be automatically unmounted after being idle for 5 minutes.

You can manually unmount with umount ./content in Linux, and fusermount -u ./content in Mac OS.

To mount raw again, simply re-run the same command. This time it will only ask for the password.


encfs is not a standard command/package. Major Linux distros have it in their repos, on Mac OS you can install using ports. (sudo port install encfs)


Faster disk imaging with dd

 $ dd if=/dev/sda bs=$(hdparm -i /dev/sda | grep BuffSize | cut -d ' ' -f 3 | tr [:lower:] [:upper:] | tr -d BUFFSIZE=,) conv=noerror | dd of=image.dd conv=noerror

— by austindcc on May 19, 2012, 3:28 a.m.


GNU dd (disk dump) copies any block device to another block device or file. It's really useful for disk cloning, but its usual invocation isn't as fast as it could be. These settings, or settings like them, often improve copying speed by more than double.

  • Piping the input of dd into the output of another instance seems to always improve copying speed.
  • /dev/sda refers to your input device, which may vary. Check yours with fdisk -l.
  • image.dd refers to the copy stored in the current working directory. You can also use another block device, such as /dev/sdb. WARNING! Be sure you know what you set the output file to! A mistake here could do irreparable damage to your system.
  • The entire hdparm subshell sets dd's input block size to the buffer size of the source medium. This also usually improves copy speed, but may need adjustment (see limitations below).
  • conv=noerror tells dd to ignore read errors.

Check dd's progress with: kill -USR1 $(pidof dd)


The hdparm subshell is not appropriate for block devices without buffers, like flash drives. Try block sizes from 512 bytes to 1 or 2MiB to get the best speed. dd usually requires root privileges to run, because it is very powerful and dangerous, and will not prompt when overwriting!. If you're not careful where dd outputs, you may permanently destroy all or part of your system. Use with care; double-check all parameters, especially the of file/device!


Run a never-ending process in the background in a way that you can check on its status anytime

 $ screen -d -m -S some_name ping my_router

— by openiduser3 on May 17, 2012, 11:03 p.m.


  • -d -m start screen in "detached" mode. This creates a new session but doesn't attach to it.
  • -S some_name gives the screen session a label, so you can easily re-attach to it with screen -R some_name
  • The shell prompt returns immediately, and of course you can logout too, the screen session will continue to run happily.
  • When the specified program exits (in this example ping), its screen window will also exit, and if there are no other windows in the screen session, then the screen session itself will also exit.

Make a hexdump or do the reverse with the xxd command

 $ xxd /path/to/binary/file

— by openiduser3 on May 16, 2012, 10:22 a.m.


This shows a very nice hexdump of the specified file. You can edit the output and convert it back to binary with xxd -r. But the best part is that you can configure vim to do all the converting back and forth for you, effectively turning vim into a binary editor, by adding this to your .vimrc:

augroup Binary
    au BufReadPre  *.bin let &bin=1
    au BufReadPost *.bin if &bin | %!xxd
    au BufReadPost *.bin set ft=xxd | endif
    au BufWritePre *.bin if &bin | %!xxd -r
    au BufWritePre *.bin endif
    au BufWritePost *.bin if &bin | %!xxd
    au BufWritePost *.bin set nomod | endif
augroup END

This will work for editing .bin files. To use it for other file extensions too, duplicate the lines within augroup and replace *.bin with *.exe for example.

This tip is from vim's :help xxd.


Really lazy way to print the first instance of $foo that occurs after $bar

 $ ifconfig | grep ^en1 -A5 | grep inet | head -n 1

— by openiduser3 on May 12, 2012, 12:30 p.m.


This is just for the sake of an example of finding $foo that occurs after $bar. Substitute ifconfig and the arguments of grep appropriately for your use case.

  • In the output of ifconfig there are several lines with inet. We want to get to the first one that comes after a line starting with en1
  • grep ^en1 -A5 will print the line starting with en1 and the next 5 lines that follow it
  • grep inet will print only the lines matching inet
  • head -n 1 will print only the first line

The value 5 in -A5 is really just a guess that the line we're interested in will be within the next 5 lines, the appropriate number depends on your use case.

Kind of a dumb technique, but it's easy to remember.


Print the first instance of $foo that occurs after $bar

 $ sed -n '\@interface Ethernet3/1@,/!/ s/ip address/&/p' file...

— by Anon5DuJaBeh on May 12, 2012, 6:27 a.m.


Should have realized this can be done with sed, too - it's even shorter!

-n suppresses the normal printing of lines.

\@interface Ethernet3/1@,/!/ specifies the beginning and end of the stanza we want to work on, and addresses all lines in between. Because the string we want to match at the beginning contains a slash, we need to designate a different character as the delimiter for the regular expression (@ in this case - note the backslash before the first one). We are OK using slashes for the ending regex, which matches an exclamation mark.

While in the stanza of interest, we slightly abuse the s function with s/ip address/&/p. This matches the text "ip address" and replaces it with... exactly the same thing (& just represents the matched text). The reason we bother doing this is to take advantage of the p flag, which will print any line where a replacement has been made.

The result is that only lines which match "ip address" will be printed, and only when we are in the stanza of interest.


sed is a little less flexible - it uses basic regular expressions while awk uses extended regular expressions. In addition, awk has a fuller set of functions and operators available, which can be used to create a wider variety of tests and actions.


Print the first instance of $foo that occurs after $bar

 $ awk '/interface Ethernet3\/1/ {instanza=1} /!/ {instanza=0} instanza && /ip address/ {print}' file...

— by Anon1UHy2ubE on May 11, 2012, 12:25 p.m.


This can easily be done by setting a variable once the lead line of the stanza is found. Take the following file as input:

interface Ethernet3/1
 ip address
 ip router isis area1
 no ip route-cache
 isis metric 10
interface Ethernet3/2
 ip address
 ip router isis area1
 no ip route-cache
 isis metric 10

The first awk pattern-action pair in the one-liner /interface Ethernet3\/1/ {instanza=1} sets the instanza variable to 1 (true) when it encounters the "interface Ethernet 3/1" line. The second pattern-action /!/ {instanza=0} resets instanza back to 0 (false) once an exclamation point is encountered, ending the desired stanza. The third pattern-action instanza && /ip address/ {print} prints any line containing "ip address," but only if we are still in the desired stanza (instanza is true): in this case, ip address

If you only wanted to see the first matching line of the first matching stanza, you could change the third action to be {print; exit} and awk would quit after printing the first match.


Sort du output in Human-readable format

 $ du -hsx * | sort -rh

— by Vaevictus on April 26, 2012, 9:08 p.m.


sort supports -h for human readable number sorting.


Probably a newer GNU only option for sort. :D


Replace symlinks with the actual files they are pointing at

 $ find /path/to/dir -type l -exec sh -c 'cp --remove-destination "$(readlink "{}")" "{}"' \; 

— by openiduser3 on April 24, 2012, 3:29 p.m.


  • All the double quoting is necessary to handle filenames with spaces.
  • Calling sh with -exec is necessary to evaluate readlink for each symlink


The BSD implementation of cp does not have the --remove-destination flag.


Expire a user's password immediately

 $ chage -d 0 USERNAME

— by openiduser3 on April 23, 2012, 11:05 p.m.


This will effectively force the user to change his/her password at next login.


Not in BSD. Yes in Linux. Don't know in UNIX.


Convert any 16:9 video to play on a QHD widescreen Android phone

 $ ffmpeg -i $1 -y -threads 0 -subq 6 -deinterlace -level 30 -f mp4 -acodec libfaac -ab 160k -ar 24000 -ac 2 -vcodec libx264 -b 1000k -maxrate 1000k -bufsize 2000k -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -coder 0 -refs 2 -flags +loop -vol 256 -trellis 1 -me_method umh -async 1 $2

— by openiduser44 on April 18, 2012, 8:18 p.m.


The Android video player is somewhat fussy about the formats it can play. This ffmpeg script will take any movie file in 16:9 widescreen format and convert it into a form that can be played on one of the current leading QHD phones such as HTC Sensation, Samsung Galaxy S2 or Motorola Atrix. Files that are merely marked as widescreen (e.g. DVD VOBs) will have to be processed into a true widescreen format such as .m2t first.


$1 the input file

$2 the output file

Output file suffix should be .mp4


ffmpeg and codecs


Create a visual report of the contents of a usb drive

 $ find /path/to/drive -type f -exec file -b '{}' \; -printf '%s\n' | awk -F , 'NR%2 {i=$1} NR%2==0 {a[i]+=$1} END {for (i in a) printf("%12u %s\n",a[i],i)}' | sort -nr

— by Anon1Qa6UsYT on April 15, 2012, 6:04 a.m.


versorge asks:

I have a bunch of usb volumes lying around and I would like to get a quick summary of what is on the drives. How much space is taken up by pdf, image, text or executable files. This could be output as a text summary, or a pie chart.

This one-liner produces a list like this:

  5804731229 FLAC audio bitstream data
   687302212 MPEG sequence
    99487460 data
    60734903 PDF document
    55905813 Zip archive data
    38430192 ASCII text
    32892213 gzip compressed data
    24847604 PNG image data
    16618355 XML 1.0 document text
    13876248 JPEG image data

The find command locates all regular files (-type f) below the given directory, which could be a mounted USB stick or any other directory. For each one, it runs the file -b command with the filename to print the file type; if this succeeds, it also prints the file size (-printf '%s\n'). This results in a list containing a file type on one line, followed by the file size on the next.

The awk script takes this as input. The GNU file command often produces very specific descriptions such as GIF image data, version 87a, 640 x 480 - to generalize these, we set the field separator to be a comma with the -F option. Referencing $1 then only uses what's to the left of the first comma, giving us a more generic description like GIF image data.

In the awk script, the first pattern-action pair NR%2 {i=$1} applies to each odd-numbered line, setting the variable i to be the file type description. The even-numbered lines are handled by NR%2==0 {a[i]+=$1}, adding the value of the line (which is the file size) to the array variable a[i]. This results in an array indexed by file type, with each array member holding the cumulative sum of bytes for that type. The END { ... } pattern-action pair finally prints out a formatted list of the total size for each file type.

At the end of the line, the sort command sorts the list, putting the file types with the largest numbers at the top.


This one-liner uses the -b option to file and the -printf primary of find - these are supported by the GNU utilities but may not work elsewhere. It can also take a long time to run, since it needs to open and analyze every file below the given directory.