Bash Cheatsheet

I've gotten tired of googling the same things over and over again.

While loops

Note to self: If you find yourself doing this, you should probably stop and reevaluate why you're not using python. Also, this is obviously an infinite loop, and is probably not going to be especially helpful.

while [ $item = true ]; do echo 'bla'; done

SCP file to a remote host with a specific port

scp -P <port>


SCP file between two remote hosts from your computer

This is useful if you have two aws instances, and want to transfer a file between them from your laptop.
scp -3 -i <pem file> user1@system_with_file:/file/to/xfer user2@system_that_needs_file:/file/to/xfer


Create sudo user non-interactively

Skip the prompts that come with creating a user typically, and give them sudoers privileges. Replace *username* with the user you want to create.

adduser --disabled-password --gecos "" *username*
touch /etc/sudoers.d/10_*username*
echo '*username* ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/10_*username*


Run function as another user

export -f <function_name>
su <user to run function as> -c "bash -c <function_name>"

Exit-on-error mode

Put this at the top of your bash script: set -e.
If a command returns a nonzero status, the shell will exit.


See files that would be unzipped without unzipping

unzip -v <file>.zip>

Unzip to a directory

unzip -d /opt


Color output in less

Use less -r <file>

Code Style

Function declarations:



Variable declaration:


Source filenames should be lowercase with underscores to separate words, i.e.


Find all bash_histories and send their contents to a file

find . -iname ".bash_history" -exec cat {} \; | tee ~/bash_histories.txt


Global variables in functions

If you want to set something as a global variable and use it in a function, do the following:

export SOMETHING="variable"

    echo $SOMETHING

Parse an env file

export $(egrep -v '^#' .env | xargs)

The env file you want to parse should look something like this:



List all directories the current user has access to

find . -maxdepth 1 -type d -perm -u=rx

Run ls -lart on all dirs current user can access

This will also display the folder at the top of the output because we've used +.

find . -maxdepth 1 -type d -perm -u=rx -exec ls -lart {} + 2>/dev/null

Find all bash_history files the current user can read

find . -maxdepth 1 -type d -perm -u=rx -print0 | xargs -0 -I{} find '{}' -readable -iname '.bash_history' 2>/dev/null

Find all .ssh directories that the current user has access to

Clean: find . -maxdepth 1 -type d -perm -u=rx -print0 | xargs -0 -I{} find '{}' -readable -type d -iname '.ssh' 2>/dev/null

Not quite as clean:

find . -maxdepth 1 -type d -perm -u=rx | xargs ls -lart 2>/dev/null |grep .ssh | grep "^.r..r..r"

Breaking this down:

find . -maxdepth 1 -type d -perm -u=rx - find all directories the current user has access to

| xargs ls -lart 2>/dev/null - send the output of the find command to ls -lart and suppress the Permission denied messages

|grep .ssh | grep "^.r..r..r" - output all files with ssh in the name with read permissions for all users

Send message to all users

echo "hi" | wall

Move file with rsync

rsync --partial --progress filename.txt user@ipaddress_or_hostname:~

Use SSH and rsync together

rsync -avzhe ssh <folder to copy> user@


Break up VM into multiple 1 GB files

Need to transfer a VM? Try this.
split -b 1000m vm.ova vm.ova.split

Bring it back together

cat vm.ova.splita* > vm.ova

Implement 3000 millisecond timeout for curl command

curl -m 3


Kill netcat after 3 seconds

Great if netcat doesn't want to die
timeout 3 nc 80; echo exit=$?


Find if string exists in a file

if grep -q SomeString "$File"; then
  Some Actions # SomeString was found


Remove last line of a file

sed -i '$ d' foo.txt


Delete files if they match a wildcard

If you have two files, someFile and someFile2, this will delete both of them:

if ls someFile* 1> /dev/null 2>&1; then
  rm someFile*


Check if multiple binaries are installed

if hash cowsay 2>/dev/null && hash gshuf 2>/dev/null; then
  # do things if both are installed

Check if file does not exist

if [ ! -f "some/file.txt" ]; then
  # do things if the file is not there

One-liner to check if file exists

if [ ! -f /tmp/foo.txt ]; then echo "File not found!"; else echo "file found"; fi


Create directory if it doesn't exist

[[ -d dir ]] || mkdir dir


View output of a running process in another bash session

strace -p <pid> -e write


Find and replace line in file

This will work with both osx and linux. It's important to note that you should not change anything except for <orig pattern>, <modified>, and file.txt.

sed -i".orig" 's/<orig pattern>/<modified>/' file.txt


Number of duplicate lines in a file

sort <file> | uniq -c


Run command in another directory as another user

This particular example is used to run a command as root in another directory

sudo -u root /bin/bash -c 'pushd "$HOME/.some_directory/"; ls -lart; popd'


Bypass post-install configurations

If you have to install things via apt and run into blue screens that require human interaction, do this to avoid it:

sudo DEBIAN_FRONTEND=noninteractive apt install -yq [packagename]


Get count of and list of most frequently used bash commands

history | awk '{a[$2]++;next}END{for (i in a){print i " --> " a[i]}}' | sort -nr -k3

Add prefix to command output

yourcommand1 | sed  's/^/[prefix1]/'

For example, this will get all ip addresses associated with running containers, and add http:// to the front of each of them:

docker ps | awk '{ print $13 }' | grep -o -P "(.*:\d+)" | sed  's/^/http:\/\//'


Reinstall a package in a debian-based system

sudo apt install --reinstall <package> -y

Unable to fetch some archives, maybe run apt-get update or try with --fix-missing

Run this if apt update --fix-missing isn't working for you:

rm -rf /var/lib/apt/lists/*; apt update

Alternatively, you can also try:

apt clean; apt update


View images on a remote system

ssh -Y user@server
apt install -y eog
eog pictures/foo.png


Show all occurences of users running ssh

find . -name .bash_history -print -exec grep ssh {} \;

Save off auth logs for review

Useful to see who has logged into your system and when

last -F > /tmp/last

"Incognito mode" for bash

Turn off history for a session.

export HISTFILE=

If you do want a record of your activity in another file, run this command instead:

export HISTFILE=0

This will create a file, 0, with your history for that session.


Find all .go files recursively

find . -name "*.go"

Remove nth line of a file

Remove the nth line of a file:

sed 'Nd' file

You have to use -i to modify the file.

For example, to remove the second line from somefile.txt and overwrite it:

sed -i '2d' somefile.txt


List NFS mounts

mount |grep nfs

When all users last logged in


All previously logged in users

lastlog |grep -v "Never"	


Find bins with SUIC or SGID set

Added output to /tmp/out.txt and backgrounded in the event you're on a crappy shell.

for i in `locate -r "bin$"`; do find $i \( -perm -4000 -o -perm -2000 \) -type f 2>/dev/null; done | tee /tmp/out.txt &

Find if host is sharing file systems

If there are local mounts, you will be able to see who you're sharing with.

showmount -e localhost

Hosts with active connections to the system

netstat -pan |grep ESTABLISHED

Search for secrets in config.xml files recursively

In this example, we are searching for patterns in config.xml files matching <secret, <password, or <credential:

find . -name "config.xml" -exec grep -iE "<secret|<password|<credential" {} + | uniq -u

Check if output of command contains a string

If file has 3 lines, tell us about it:

if [[ $(wc -l file) == *3* ]]; then
  echo "There are three lines in file"


Find all csv files and delete them

find . -name "*.csv" -exec rm {} +


strace /bin/ls

Filter on write functions:

strace -e write /bin/ls


Used to get the assembly output of a given binary

objdump -d <binary> | tee binary_output.txt


There's a whole page I've dedicated to this:

List largest directories and files

du -hsx * | sort -rh | head -10


Destroy all json files recursively

find . -name "*.json" -exec rm {} \;


Semicolon vs + in find


Show all executable files

find . -maxdepth 1 -perm -111 -type f


Check if you can ssh to several hosts


for SERVER in $(cat hosts.txt); do
  ssh -i id_rsa -o StrictHostKeyChecking=no -o BatchMode=yes user@$SERVER exit && echo OK $SERVER || echo ERR $SERVER



List tickets in a keytab

ktutil -kt file.keytab list


Create kerberos ticket

kinit <username> -k -t /where/to/store/keytab/nameofkeytab.keytab

Not matching with grep

This example will find all jobs that don't contain com:

launchctl list | grep -v com

Regexing with grep

This will get the version of ruby from rvm:
rvm list | head -n 1 |grep -Po '\-(.*?)\s' | tail -c +2
The output from that command that it is parsing will look something like this: ruby-2.5.1 [ x86_64 ]

It will return 2.5.1.


Create self-signed cert

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365


Create SSH key script

if [ ! -e ~/.ssh/ ]; then
  echo 'Creating your ssh public and private key'
  echo '----------------------------------------'

  # Create public and private 2048 bit ssh key pair without pw prompt
  ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -N ''

  # Copy new key to make it possible to autologin
  cat ~/.ssh/ >> ~/.ssh/authorized_keys
  chmod 0600 ~/.ssh/authorized_keys

  # Add the ssh key
  ssh-add ~/.ssh/id_rsa
  echo "Public ssh key file already exists"
  echo "----------------------------------------"


Untar to specific directory

tar -xf archive.tar -C /target/directory


Show successful ssh logins

grep sshd.\*Accepted /var/log/auth.log

Show failed ssh logins

grep sshd.\*Failed /var/log/auth.log

Create encrypted zip

zip -r original_file
openssl enc -in -aes-256-cbc -e >
# enter password when prompted

Depending on the situation, you may consider destroying the original unencrypted file:


Decrypt and unzip encrypted zip

openssl enc -in -aes-256-cbc -d >
# enter password when prompted

Remove duplicates from a file

sort inputFile | uniq -u > outputfile

Use curl to upload a file

To upload a file to an endpoint at /upload with a form field, fileUpload, you can do the following:

curl -F "fileUpload=@test.txt" -vvv

Use curl to download a file

This will also ensure that if a proxy is in place, it will not be used to connect to

curl --output puppet-linux -vvvv --noproxy


Check if a string is a timestamp

date -r <string>

For example:

date -r 1530279830


Kill all python processes in Ubuntu

pkill python