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.

Tags

6

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.

Explanation

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

6

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.

Explanation

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

5

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.

Explanation

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

5

Generate a sequence of numbers

 $ echo {01..10}

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

Explanation

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.

Limitations

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

5

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.

Explanation

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.

Enjoy!

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

Limitations

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 :)

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.

Explanation

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 :-)

4

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.

Explanation

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

Limitations

The case modification extension is available since Bash 4.

4

Show dd status every so often

 $ watch --interval 5 killall -USR1 dd

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

Explanation

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

3

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.

Explanation

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

3

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.

Explanation

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.

3

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.

Explanation

Using sed to remove a specific line.

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

Limitations

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

2

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.

Explanation

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!

Limitations

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.

2

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.

Explanation

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.

Limitations

This is Mac OSX specific. Use xsel on Linux.

2

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.

Explanation

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.

Limitations

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.

2

Generate a sequence of numbers

 $ for ((i=1; i<=10; ++i)); do echo $i; done

— by Janos on Nov. 4, 2014, 12:29 p.m.

Explanation

This is similar to seq, but portable. seq does not exist in all systems and is not recommended today anymore. Other variations to emulate various uses with seq:

# seq 1 2 10
for ((i=1; i<=10; i+=2)); do echo $i; done

# seq -w 5 10
for ((i=5; i<=10; ++i)); do printf '%02d\n' $i; done

2

Compute factorial of positive integer

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

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

Explanation

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
3628800

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)
1
1
2
3
4

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

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

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

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

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

2

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.

Explanation

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'

2

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.

Explanation

Actual conditions without erasing, remove from the repository.

2

Dump network traffic with tcpdump to file with time-stamp in its filename

 $ date +"%Y-%m-%d_%H-%M-%Z" | xargs -I {} bash -c "sudo tcpdump -nq -s 0 -i eth0 -w ./dump-{}.pcap"

— by kowalcj0 on May 17, 2013, 8:03 p.m.

Explanation

will dump the traffic into a file with a time-stamp in its name. Example filename:

dump-2013-05-17_15-46-UTC.pcap

2

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.

Explanation

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 (-).

Limitations

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

2

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.

Explanation

  • 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 \;

Limitations

Requires the ImageMagick image manipulation tool.

2

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.

Explanation

  • 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

1

Retrieve dropped connections from firewalld journaling

 $ sudo journalctl -b | grep -o "PROTO=.*" | sed -r 's/(PROTO|SPT|DPT|LEN)=//g' | awk '{print $1, $3}' | sort | uniq -c

— by FoxBuru on Sept. 14, 2017, 5:10 p.m.

Explanation

We take the output of journalctl since the last boot (-b flag) and output from PROTO= until the EOL. Then, we remove identification tags (PROTO=/SPT=/DPT=/LEN=) and print just the protocol and destination port (cols 1 and 3). We sort the output properly so we can aggregate them on the call over uniq.

Limitations

  • Only works on Linux
  • You use firewalld and you have logging set on ALL (see firewalld.conf for details)
  • You use journald for logging
  • Your user has sudo privileges

1

Get the latest Arch Linux news

 $ w3m https://www.archlinux.org/ | sed -n "/Latest News/,/Older News/p" | head -n -1

— by Jab2870 on Aug. 15, 2017, 10:35 a.m.

Explanation

w3m is a terminal web browser. We use it to go to https://www.archlinux.org/

We then use sed to capture the text between Latest News and Older News.

We then get rid of the last line which is Older News.

Limitations

For this, w3m would need to be installed. It should be installable on most systems.

If Arch change the format of there website significantly, this might stop working.

1

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.

Explanation

Paste this function in the ~/.bashrc file.

Usage:

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.