We collect practical, well-explained Bash one-liners, and promote best practices in Bash shell scripting. To get the latest Bash one-liners, follow @bashoneliners on Twitter. If you find any problems, report a bug on GitHub.



Displays the quantity of connections to port 80 on a per IP basis

 $ clear;while x=0; do clear;date;echo "";echo "  [Count] | [IP ADDR]";echo "-------------------";netstat -np|grep :80|grep -v LISTEN|awk '{print $5}'|cut -d: -f1|uniq -c; sleep 5;done

— by cesp on April 9, 2014, 5:49 a.m.


Uses an infinite loop to display output from netstat, reformatted with grep, awk, and cut piped into uniq to provide the count. Complete with a pretty header. Polls every 5 seconds


Show 10 Largest Open Files

 $ lsof / | awk '{ if($7 > 1048576) print $7/1048576 "MB" " " $9 " " $1 }' | sort -n -u | tail

— by cellojoe on Feb. 28, 2014, 3:34 a.m.


Show the largest 10 currently open files, the size of those files in Megabytes, and the name of the process holding the file open.


Convert directory of videos to MP4 in parallel

 $ for INPUT in *.avi ; do echo "${INPUT%.avi}" ; done | xargs -i -P9  HandBrakeCLI -i "{}".avi -o "{}".mp4

— by shavenwarthog on Aug. 13, 2013, 5:10 a.m.


This oneliner uses the wonderful Handbrake program to convert videos. We convert a directory of AVIs at a time, in parallel.

The first three bits ("for INPUT...done |") lists the AVI files in the current directory, then uses a Bash function to strip off the suffix. It then sends each video file name to the next part.

The next part of the command (| xargs ...) runs our converter in parallel. The "-i" flag says take each input (video file name) and stick it in the "{}" parts of the xargs command. The parallel option lets us run up to 9 commands at the same time ("-P9").

The last part (HandBrakeCLI -i "{}".avi -o "{}".mp4) converts a single video to MP4 format. The two open-close curly braces are replaced with xargs, once per input video file. The first run through will be "HandBrakeCLI -i "input1".avi -o "input1".mp4", next will be "HandBrakeCLI -i "input2".avi -o "input2".mp4", etc.


Another version of this writeup is on my blog: http://johntellsall.blogspot.com/2013/08/converting-video-for-media-player.html


Converting videos in parallel is confusing as Handbrake overwrites the status for every file -- ignore the screen.

install Handbrake from http://handbrake.fr/

It also has a pretty GUI for those who don't like the terminal :)


List status of all GIT repos

 $ find ~ -name ".git" 2> /dev/null | sed 's/\/.git/\//g' | awk '{print "-------------------------\n\033[1;32mGit Repo:\033[0m " $1; system("git --git-dir="$1".git --work-tree="$1" status")}'

— by uMt on Oct. 16, 2016, 11:19 p.m.


  • List all .git dirs
  • Trim .git parts
  • Run git --git-dir=X.git --work-tree=X status with awk


Generate a sequence of numbers

 $ echo {01..10}

— by Elkku on March 1, 2015, 12:04 a.m.


This example will print:

01 02 03 04 05 06 07 08 09 10

While the original one-liner is indeed IMHO the canonical way to loop over numbers, the brace expansion syntax of Bash 4.x has some kick-ass features such as correct padding of the number with leading zeros.


The zero-padding feature works only in Bash >=4.


Corporate random bullshit generator (cbsg)

 $ curl -s http://cbsg.sourceforge.net/cgi-bin/live | grep -Eo '^<li>.*</li>' | sed s,\</\\?li\>,,g | shuf -n 1

— by Genunix on Sept. 4, 2014, 3:44 p.m.


This one-liner will just use cbsg.sourceforge.net/cgi-bin/live and grab one random corporate bullshit. Good to use when deprecating command line tools in your corporation :-)


Show dd status every so often

 $ watch --interval 5 killall -USR1 dd

— by FoxWilson on Dec. 6, 2012, 6:16 p.m.


The dd command has no progress indicator. While copying large files it may seem like nothing is happening, as dd prints nothing until completed. However, when the dd process receives USR1 signal, it prints I/O statistics to standard error and resumes copying. Here we use killall to send the signal, and we call it with watch to repeat this every 5 seconds, effectively giving a progress indicator to good old dd.

Start in one window the watch:

$ watch --interval 5 killall -USR1 dd

Start copying in another:

$ dd if=/dev/random of=junk bs=1000 count=1000 
dd: warning: partial read (13 bytes); suggest iflag=fullblock
0+2 records in
0+2 records out
21 bytes (21 B) copied, 3.01687 s, 0.0 kB/s
0+3 records in
0+3 records out
29 bytes (29 B) copied, 8.02736 s, 0.0 kB/s


Change the encoding of all files in a directory and subdirectories

 $ find . -type f  -name '*.java' -exec sh -c 'iconv -f cp1252 -t utf-8 "$1" > converted && mv converted "$1"' -- {} \;

— by Janos on Nov. 20, 2014, 12:15 p.m.


The parameters of find:

  • . -- search in the current directory, and its subdirectories, recursively
  • -type f -- match only files
  • -name '*.java' -- match only filenames ending with .java
  • -exec ... \; -- execute command

The command to execute is slightly complicated, because iconv doesn't rewrite the original file but prints the converted content on stdout. To update the original file we need 2 steps:

  1. Convert and save to a temp file
  2. Move the temp file to the original

To do these steps, we use a sh subshell with -exec, passing a one-liner to run with the -c flag, and passing the name of the file as a positional argument with -- {}.

Unfortunately the redirection will use UNIX style line endings. If the original files have DOS style line endings, add this command in the subshell:

vim +'set ff=dos' +wq converted


Remove offending key from known_hosts file with one swift move

 $ ssh-keygen -R <hostname>

— by openiduser126 on Jan. 25, 2014, 1:35 p.m.


The ssh-keygen tool comes with an option for this already, there is no need for esoteric one-liners that are hard to remember.

Say you ssh server.example.com and its host key has changed because you just reinstalled it. Run ssh-keygen -R server.example.com then try to connect to the server again, you'll be presented with the option to save the host key just like new.


Rename all items in a directory to lower case

 $ for i in *; do mv "$i" "${i,,}"; done

— by EvaggelosBalaskas on April 20, 2013, 9:41 p.m.


Loop over the items in the current directory, and use Bash built-in case modification expansion to convert to lower case.


The case modification extension is available since Bash 4.


Remove offending key from known_hosts file with one swift move

 $ sed -i 18d .ssh/known_hosts

— by EvaggelosBalaskas on Jan. 16, 2013, 2:29 p.m.


Using sed to remove a specific line.

The -i parameter is to edit the file in-place.


This works as posted in GNU sed. In BSD sed, the -i flag requires a parameter to use as the suffix of a backup file. You can set it to empty to not use a backup file:

sed -i'' 18d .ssh/known_hosts


Ban all IPs that attempted to access phpmyadmin on your site

 $ grep "phpmyadmin" $path_to_access.log | grep -Po "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" | sort | uniq | xargs -I% sudo iptables -A INPUT -s % -j DROP

— by openiduser187 on April 2, 2015, 8:58 a.m.


Cheap security Bash one-liner to ban all IPs that are probably doing automated attacks.

Make sure your IP isn't listed before piping through iptables drop!!

  1. This will first find all lines in $path_to_access.log that have phpmyadmin in them,

  2. Then grep out the ip address from the start of the line,

  3. Then sort and unique them,

  4. Then add a rule to drop them in iptables

Again, just edit in echo % at the end instead of the iptables command to make sure your IP isn't in there. Don't inadvertently ban your access to the server!


You may need to change the grep part of the command if you're on mac or any system that doesn't have grep -P.


Run a command and copy its output to clipboard (Mac OSX)

 $ echo "Here comes the output of my failing code" | tee >(pbcopy)

— by Elkku on Feb. 28, 2015, 11:53 p.m.


Often you need to copy the output of a program for debugging purposes. Cool kids on the block may use pastebin servers. But what if you'd just like to copy-and-paste the output to a web form, say?

This one-liner gives a nice demonstration of process substitution. The stdout is piped to tee for duplication. Rather than dumping the output to a file as in the normal case, the output is piped to pbcopy via a temporary file that the OS conjures up on the fly (/dev/fd/XXX). The end result: you can paste the output wherever you want with Command+V.


This is Mac OSX specific. Use xsel on Linux.


Nmap scan every interface that is assigned an IP

 $ ifconfig -a | grep -Po '\b(?!255)(?:\d{1,3}\.){3}(?!255)\d{1,3}\b' | xargs nmap -A -p0-

— by ratchode on Feb. 8, 2015, 2:11 a.m.


ifconfig -a to output all interfaces, | grep -Po '\b(?!255)(?:\d{1,3}\.){3}(?!255)\d{1,3}\b' will search for 4 octets with up to three digits each, ignoring any leading or trailing 255. For my personal, and likely most local networks, this will exclude broadcast and netmask addresses without affecting host IPs. At this point, stdout holds any IP assigned to an interface, and will finally pipe to xargs, which supplies the IPs as arguments for nmap. Nmap then performs an OS detection, version detection, script, and traceroute scan on all 65536 ports of each assigned IP.

Note: When using grep, -P is requrired to be able to interpret negative lookahead (?!) and non-capturing group (?:) brackets.


The regex epression will find both valid and non-valid IP addresses, e.g. 999.999.999.999, however invalid IPs are not an expected result of ifconfig -a. It is possible to correct this with a much longer regex expression, but not necessary in this case.


Compute factorial of positive integer

 $ fac() { (echo 1; seq $1) | paste -s -d\* | bc; }

— by jeroenjanssens on May 21, 2014, 10:55 p.m.


This one-liner defines a shell function named fac that computes the factorial of a positive integer. Once this function has been defined (you can put it in your .bashrc), you can use it as follows:

$ fac 10

Let's break the function down. Assume that we want to compute the factorial of 4. First, it echo's 1, so that the factorial of 0 works correctly (because seq 0 outputs nothing). Then, seq is used to generate a list of numbers:

$ (echo 1; seq 4)

Then, it uses paste to put these numbers on one line, with * (multiplication) as the seperator:

$ (echo 1; seq 4) | paste -s -d\*

Finally, it passes this "equation" to bc, which evalutes it:

$ (echo 1; seq 4) | paste -s -d\* | bc

The actual function uses $1 so that we can compute the factorial of any positive integer using fac.


Find all files recursively with specified string in the filename and output any lines found containing a different string.

 $ find . -name *conf* -exec grep -Hni 'matching_text' {} \; > matching_text.conf.list

— by n00tz on April 14, 2014, 8:23 p.m.


find . -name *conf* In current directory, recursively find all files with 'conf' in the filename.

-exec grep -Hni 'matching_text' {} \; When a file is found matching the find above, execute the grep command to find all lines within the file containing 'matching_text'.

Here are what each of the grep switches do:

grep -i ignore case.

grep -H print the filename

grep -n print the line number

> matching_text.conf.list Direct the grep output to a text file named 'matching_text.conf.list'


Remove .DS_Store from the repository you happen to staging by mistake

 $ find . -name .DS_Store -exec git rm --ignore-unmatch --cached {} +

— by Kuwana on Feb. 22, 2014, 9:45 a.m.


Actual conditions without erasing, remove from the repository.


Tree-like output in ls

 $ ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/   /' -e 's/-/|/'

— by clitips on April 26, 2013, 1:37 p.m.


This one-liner initially does a recursive listing of the current directory: ls -R.

Any output other that the directory names, identified by : at the very end of each line (hence :$), is filtered out: grep ":$".

Finally there's a little of sed magic replacing any hierarchy level (/) with dashes (-).


Works for me with Bash under Linux, Mac OS X, Solaris.


Create a thumbnail from the first page of a PDF file

 $ convert -thumbnail x80 file.pdf[0] thumb.png

— by Janos on Feb. 6, 2013, 9:44 p.m.


  • convert is part of ImageMagick image manipulation tool
  • -thumbnail x80 means create a thumbnail image of height 80 pixels, the width will be automatically chosen to make the image proportional
  • The [0] is to create a thumbnail for the first page only, without that a thumbnail image would be created for each page in the pdf file

To do this for all PDF files in a directory tree:

find /path/to/dir -name '*.pdf' -exec convert -thumbnail x80 {}[0] {}-thumb.png \;


Requires the ImageMagick image manipulation tool.


How to send an http POST to a website with a file input field

 $ curl -L -v -F "value=@myfile" "http://domain.tld/whatever.php"

— by openiduser14 on Feb. 15, 2012, 11:26 p.m.


  • curl read "man curl" if you need to info like using cookies,etc. you can also use wget
  • -L follow redirects
  • -v be verbose
  • -F an input field
  • value= the name of the input field
  • @myfile the file you want uploaded
  • "http://domain.tld/whatever.php" the url that will take the file


Make a new folder and cd into it.

 $ mkcd(){ NAME=$1; mkdir -p "$NAME"; cd "$NAME"; }

— by PrasannaNatarajan on Aug. 3, 2017, 6:49 a.m.


Paste this function in the ~/.bashrc file.


mkcd name1

This command will make a new folder called name1 and cd into the name1.

I find myself constantly using mkdir and going into the folder as the next step. It made sense for me to combine these steps into a single command.


Listen to the radio (radio2 in example)

 $ mpv http://a.files.bbci.co.uk/media/live/manifesto/audio/simulcast/hls/uk/sbr_med/llnw/bbc_radio_two.m3u8

— by Jab2870 on July 19, 2017, 2:44 p.m.


MPV is a terminal audio player. You could also use vlc or any media player that supports streams.

To find a stream for your favourite uk radio station, look here: UK Audio Streams. If you are outside of the uk, Google is your friend


Requires an audio player that supports streams.


Go up to a particular folder

 $ alias ph='cd ${PWD%/public_html*}/public_html'

— by Jab2870 on July 18, 2017, 6:07 p.m.


I work on a lot of websites and often need to go up to the public_html folder.

This command creates an alias so that however many folders deep I am, I will be taken up to the correct folder.

alias ph='....': This creates a shortcut so that when command ph is typed, the part between the quotes is executed

cd ...: This changes directory to the directory specified

PWD: This is a global bash variable that contains the current directory

${...%/public_html*}: This removes /public_html and anything after it from the specified string

Finally, /public_html at the end is appended onto the string.

So, to sum up, when ph is run, we ask bash to change the directory to the current working directory with anything after public_html removed.


If I am in the directory ~/Sites/site1/public_html/test/blog/ I will be taken to ~/Sites/site1/public_html/

If I am in the directory ~/Sites/site2/public_html/test/sources/javascript/es6/ I will be taken to ~/Sites/site2/public_html/


Open another terminal at current location

 $ $TERMINAL & disown

— by Jab2870 on July 18, 2017, 3:04 p.m.


Opens another terminal window at the current location.

Use Case

I often cd into a directory and decide it would be useful to open another terminal in the same folder, maybe for an editor or something. Previously, I would open the terminal and repeat the CD command.

I have aliased this command to open so I just type open and I get a new terminal already in my desired folder.

The & disown part of the command stops the new terminal from being dependant on the first meaning that you can still use the first and if you close the first, the second will remain open.


It relied on you having the $TERMINAL global variable set. If you don't have this set you could easily change it to something like the following:

gnome-terminal & disown or konsole & disown


Generate a sequence of numbers

 $ perl -e 'print "$_\n" for (1..10);'

— by abhinickz6 on May 30, 2017, 2:47 p.m.


Print the number with newline character which could be replaced by any char.