DEV Community

Cover image for 5 Handy Bash Tricks in 2 Minutes
Jacob Herrington (he/him)
Jacob Herrington (he/him)

Posted on • Updated on

5 Handy Bash Tricks in 2 Minutes

This article should only take you a couple of minutes to read, and you'll walk away with a handful of the bash tricks I constantly use.

1. Make a directory and navigate to it

mkdir /foo/bar && cd $_
Enter fullscreen mode Exit fullscreen mode

In bash, $_ is a reference to the last parameter that was used. It can come in handy all over the place. Generally, the best use for $_ is to avoid repeating yourself in cases like the above example.

2. Backup a file without typing it twice

cp /some/path/to/file.txt{,.bak}
Enter fullscreen mode Exit fullscreen mode

This feature of bash is called brace expansion, it has a ton of useful applications. This is just one I sometimes use when I want to create a copy of a file quickly.

3. Backup every file in a folder

for file in * ; do cp "$file" "$file".bak; done
Enter fullscreen mode Exit fullscreen mode

In this oneliner, we are taking advantage of bash's ability to loop over the files in a directory.

Frequently, I find myself using this syntax to avoid using multiple lines.

4. Find a command by its description

apropos "some description"
Enter fullscreen mode Exit fullscreen mode

apropos is a command that looks through the commands on your machine for one that has a description like the one you provided.

It can be extremely useful when you remember what a command does, but not its name.

5. Repeat the last command with sudo

sudo !!
Enter fullscreen mode Exit fullscreen mode

!! is a quick way to repeat the last command. I do this a ton.

Feel free to add your own useful bash tricks in the comments. 🤠

Top comments (22)

learnbyexample profile image

Nice list.

Please please please please please use double quotes around variables, unless you explicitly desire the shell to interpret the variable value. A simple example to illustrate the issue:

$ mkdir test_shell_behavior && cd $_
$ touch 'foo' 'xyz 123'
$ for file in * ; do cp $file $file.bak; done
cp: target '123.bak' is not a directory
$ ls
foo  foo.bak  xyz 123

$ rm foo.bak
$ for file in * ; do cp "$file" "$file".bak; done
$ ls
foo  foo.bak  xyz 123  xyz 123.bak
Enter fullscreen mode Exit fullscreen mode

See this Q&A on unix.stackexchange and wooledge: Quotes for more details.

You can also use man -k instead of apropos

For testing shell globs, you can use echo

$ echo cp /some/path/to/file.txt{,.bak}
cp /some/path/to/file.txt /some/path/to/file.txt.bak
Enter fullscreen mode Exit fullscreen mode
jacobherrington profile image
Jacob Herrington (he/him)

Cool! Thanks for the feedback, that is good advice. 🤠

vasilvestre profile image
Valentin Silvestre

I definitly recommand ${variable}, much better to look and feel more like you can't be wrong about it :)

zeddotes profile image
zeddotes • Edited

To piggyback on the last one there, if you history:

$ history

the output should be a numerical list of commands you've entered in the past, like so:

10016  git status
10017  git commit
10018  git push origin master

If I wanted to run git status again (ie, repeat command 10016 from history), I could do something like this:

$ !10016

jacobherrington profile image
Jacob Herrington (he/him)

That's a great trick! Thanks!

zeddotes profile image
zeddotes • Edited

You could also pipe history too! Which could allow you to grep (and more) within your history:

$ history | grep "status"

10005  git status
10008  git status
10011  git status
10014  git status
10016  git status


Thread Thread
ianturton profile image
Ian Turton

ctrl-r status will walk back up your history looking at each time the command line contained status - just hit return when you find the command you need.

ssimontis profile image
Scott Simontis

My favorite piece of knowledge:

If you choose to make an alias for sudo, you should ensure there is a space at the end, or else the shell will not expand any more aliases within the command.

So if I wanted to use please instead of sudo, I would need to do:

alias please="sudo "

I am always tempted to put spaces around the equals sign, probably my #1 scripting mistake.

alsargent profile image
Al Sargent

Some of my regular bash commands:

A simple way to monitor network connectivity and latency -- ping a highly-available domain like

ping | while read pong; do echo "$(date): $pong"; done

I also like to use alias to shorten frequently-used commands and parameters. Here are some examples from my .bashrc:

alias l="ls -aF"
alias ll="ls -laF"
alias c="cd"
alias m="more"
alias e="env | sort"
alias h='history'
alias p="pwd"
alias g="go run"
alias cd..='cd ..'
alias c..='cd ..'
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias .....='cd ../../../..'
alias ......='cd ../../../../..'

Print each PATH entry on a separate line:

alias path='echo -e ${PATH//:/\n}'

Open the current directory in macOS Finder:

alias o="open ."

fernandomaia profile image
Fernando Maia • Edited

Really cool! Just learned about $_.

If anyone wants, I just created a function to perform the first item on the list in a single command.

function mdcd {
    command mkdir $1 && cd $1

This should work with bash and zsh, and should be added to their config files(.bashrc and .zshrc, respectively).

nickhuanca profile image
Nick Huanca

Just a heads up, globbing in your "backup every file" example will miss all dotfiles. You could do a dual expansion in this case for i in * .*; do echo "${i}"; done but this also includes . and .. in this glob. YMMV depending on what you're doing with the list.

jacobherrington profile image
Jacob Herrington (he/him)

Thanks for the heads up!

simbo1905 profile image
Simon Massey • Edited

ctrl+r to search back through your command history to rerun a command is something that I find surprises people

vim folks will also love setting vi as the keyboard shortcuts to edit lines in Bash with set -o v within their profile. you can then up arrow (or ctrl+r) to find a previous command, hit Esc to exit insert mode to activate vi shortcuts then to edit the line. For example command 0 (zero) takes you to the beginning of the line, w jumps over words, r will let you overwrite, a to start appending, d3w will delete three words. Using vi shortcuts can save a serious amount of typing.

Folks on windows who like bash and who use visual studio code might like my post on setting Git Bash to be the built in terminal within VS Code.

peterwitham profile image
Peter Witham

Thanks for these, sometimes it's the little things that you forget and need to read to be reminded. The create folder and change to it is priceless, I turned my one into a function so I can use it generically.

dbazuin profile image
Dirk Bazuin

When using mkdir to create /foo/bar adding -p makes sure that /foo is also created if is does not exist yet.

kristian profile image

In number 3, is moving every file in a folder just an example to illustrate using a for loop? Or is there a reason why you wouldn't do it like this:

mv * ../elsewhere/
jacobherrington profile image
Jacob Herrington (he/him)

Haha, no.

I updated it to a more legitimate use. I didn't actually want to use the example of making backups twice in a row, but the moving example didn't make sense. 🙃

andyyaldoo profile image
Andy Aldo Dharmawan • Edited

For point number 2, does it expand to

cp /some/path/to/file.txt /some/path/to/file.bak


If so, shouldn't it be

cp /some/path/to/file{.txt,.bak}


learnbyexample profile image

I guess the author wished to only add a suffix, not change the extension itself.

$ echo /some/path/to/file.txt{,.bak}
/some/path/to/file.txt /some/path/to/file.txt.bak
jacobherrington profile image
Jacob Herrington (he/him)

Either one works here. I usually leave the original file extension on these!

brianjenkins94 profile image
Brian Jenkins • Edited

If you're writing shell scripts, and you're not using ShellCheck, you're missing out.

jacobherrington profile image
Jacob Herrington (he/him)

Good advice!