Jay Taylor's notes

back to listing index

What is your single most favorite command-line trick using Bash?

[web search]
Original source (stackoverflow.com)
Tags: bash command-line one-liners scripting stackoverflow.com
Clipped on: 2016-08-31

156 favorite
644

We all know how to use <ctrl>-R to reverse search through history, but did you know you can use <ctrl>-S to forward search if you set stty stop ""? Also, have you ever tried running bind -p to see all of your keyboard shortcuts listed? There are over 455 on Mac OS X by default.

What is your single most favorite obscure trick, keyboard shortcut or shopt configuration using bash?

locked by Robert Harvey Oct 5 '11 at 3:09

This question exists because it has historical significance, but it is not considered a good, on-topic question for this site, so please do not use it as evidence that you can ask similar questions here. This question and its answers are frozen and cannot be changed. More info: help center.

closed as not a real question by Shog9 May 27 '11 at 21:59

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.If this question can be reworded to fit the rules in the help center, please edit the question.

2 upvote
  flag
Please reword this to say "What is your single most favourite". This allows people to up-vote specific answers, almost like a poll. – SCdF Sep 16 '08 at 1:08
1 upvote
  flag
There is a StackOverflow clone for this very question: commandlinefu.com – rkb Apr 15 '09 at 16:54
158

Renaming/moving files with suffixes quickly:
cp /home/foo/realllylongname.cpp{,-old}

This expands to:
cp /home/foo/realllylongname.cpp /home/foo/realllylongname.cpp-old

community wiki

12 upvote
  flag
Awesome! Now I need to try and remember this one. – Jon Ericson Sep 16 '08 at 6:23
9 upvote
  flag
Just to point out that to do the reverse (going from .cpp-old to .cpp) you'd do cp /home/foo/realllylongname.cpp{-old,} – mike Sep 3 '10 at 16:03
150
cd -

It's the command-line equivalent of the back button (takes you to the previous directory you were in).

community wiki

6 upvote
  flag
I prefer to use pushd and popd to maintain a directory stack, myself. – Pi. Sep 16 '08 at 1:37
21 upvote
  flag
But 'cd -' has the advantage of working even if you didn't remember to use pushd. – Sergio Acosta Sep 16 '08 at 5:50
10 upvote
  flag
It's worth mentioning that 'cd' takes you to your home directory. – dr-jan Sep 19 '08 at 19:14
135

Another favorite:

!!

Repeats your last command. Most useful in the form:

sudo !!
community wiki

81 upvote
  flag
it has the added benefit of making you sound really angry about it too. "Computer, do this." "Access denied". "DO IT!!" – nickf Sep 16 '08 at 1:16
10 upvote
  flag
Similar things you can do: mkdir testdir; cd !$.. This runs cd [last word of previous line] (in the example, cd testdir) – dbr Sep 16 '08 at 10:07
13 upvote
  flag
Make Me A Sandwich Sudo !! – Kibbee Apr 15 '09 at 16:45
4 upvote
  flag
sudo sounds japanese too. I can perfectly picture an angry samurai yelling it before brandishing his katana. "SUDO !!" – mike Aug 23 '09 at 8:35
82

My favorite is '^string^string2' which takes the last command, replaces string with string2 and executes it

$ ehco foo bar baz
bash: ehco: command not found
$ ^ehco^echo
foo bar baz

Bash command line history guide

community wiki

9 upvote
  flag
!!:gs/ehco/echo/ – andre-r Sep 26 '09 at 12:10
1 upvote
  flag
@andre-r: !!:gs/ehco/echo/ performs a global search and replace on the last command (confer !! in stackoverflow.com/questions/68372/…). That is not equivalent to ^ehco^echo which just replaces one instance of "ehco" -- a more accurate response would be !!:s/ehco/scho. – Iceland_jack Jul 30 '10 at 19:29
64

rename

Example:

$ ls
this_has_text_to_find_1.txt
this_has_text_to_find_2.txt
this_has_text_to_find_3.txt
this_has_text_to_find_4.txt

$ rename 's/text_to_find/been_renamed/' *.txt
$ ls
this_has_been_renamed_1.txt
this_has_been_renamed_2.txt
this_has_been_renamed_3.txt
this_has_been_renamed_4.txt

So useful

community wiki

3 upvote
  flag
Wow, I've been a moron all these years using basename, mv and {} tricks to do this. /foreheadsmack. – Gregg Lind Oct 23 '08 at 21:13
7 upvote
  flag
rename isn't bash/readline specific like the other posts however. – guns Mar 12 '09 at 14:49
1 upvote
  flag
zmv from zsh distribution is much better in most cases. – ZyX May 24 '10 at 6:07
61

I'm a fan of the !$, !^ and !* expandos, returning, from the most recent submitted command line: the last item, first non-command item, and all non-command items. To wit (Note that the shell prints out the command first):

$ echo foo bar baz
foo bar baz
$ echo bang-dollar: !$ bang-hat: !^ bang-star: !*
echo bang-dollar: baz bang-hat: foo bang-star: foo bar baz
bang-dollar: baz bang-hat: foo bang-star: foo bar baz

This comes in handy when you, say ls filea fileb, and want to edit one of them: vi !$ or both of them: vimdiff !*. It can also be generalized to "the nth argument" like so:

$ echo foo bar baz
$ echo !:2
echo bar
bar

Finally, with pathnames, you can get at parts of the path by appending :h and :t to any of the above expandos:

$ ls /usr/bin/id
/usr/bin/id
$ echo Head: !$:h  Tail: !$:t
echo Head: /usr/bin Tail: id
Head: /usr/bin Tail: id
community wiki

8 upvote
  flag
add "bind Space:magic-space" to .bashrc and any ! combination will be automatically expanded when you hit space. – Yoo Sep 13 '09 at 16:48
47 accepted

When running commands, sometimes I'll want to run a command with the previous ones arguments. To do that, you can use this shortcut:

$ mkdir /tmp/new
$ cd !!:*

Occasionally, in lieu of using find, I'll break-out a one-line loop if I need to run a bunch of commands on a list of files.

for file in *.wav; do lame "$file" "$(basename "$file" .wav).mp3" ; done;

Configuring the command-line history options in my .bash_login (or .bashrc) is really useful. The following is a cadre of settings that I use on my Macbook Pro.

Setting the following makes bash erase duplicate commands in your history:

export HISTCONTROL="erasedups:ignoreboth"

I also jack my history size up pretty high too. Why not? It doesn't seem to slow anything down on today's microprocessors.

export HISTFILESIZE=500000
export HISTSIZE=100000

Another thing that I do is ignore some commands from my history. No need to remember the exit command.

export HISTIGNORE="&:[ ]*:exit"

You definitely want to set histappend. Otherwise, bash overwrites your history when you exit.

shopt -s histappend

Another option that I use is cmdhist. This lets you save multi-line commands to the history as one command.

shopt -s cmdhist

Finally, on Mac OS X (if you're not using vi mode), you'll want to reset <CTRL>-S from being scroll stop. This prevents bash from being able to interpret it as forward search.

stty stop ""
6 upvote
  flag
I find "Alt-." much better than "!!:*" for repeating the last word of the last command. – Weidenrinde Sep 17 '08 at 23:34
43

How to list only subdirectories in the current one ?

ls -d */

It's a simple trick, but you wouldn't know how much time I needed to find that one !

community wiki

2 upvote
  flag
Excellent! All these years the best I could come up with was alias lsd='ls -F | grep --color /', which would list the same thing but in a more lame fashion. However, it would list one dir per line, for ease of parsing. I've modified your command to do the same: ls -d1 */ – Artem Russakovskii Aug 4 '09 at 15:06
1 upvote
  flag
It is a bit tricky... "ls -d" is similar to "ls -d ./" and "ls -d /" to "ls -d ./*/". The '-d' switch set 'ls' tu list only directory entries, but if you give it no parameter, it use the current directory as a parameter, so it has *only the "." directory to list... – edomaur Sep 14 '09 at 22:54
1 upvote
  flag
I can't believe I've never discovered this before. Great tip. – Nick Dixon Jan 20 '10 at 10:29
41

ESC.

Inserts the last arguments from your last bash command. It comes in handy more than you think.

cp file /to/some/long/path

cd ESC.

9 upvote
  flag
Also alt-. is the same thing. – Mark Baker Oct 27 '08 at 11:17
36

Sure, you can "diff file1.txt file2.txt", but Bash supports process substitution, which allows you to diff the output of commands.

For example, let's say I want to make sure my script gives me the output I expect. I can just wrap my script in <( ) and feed it to diff to get a quick and dirty unit test:

$ cat myscript.sh
#!/bin/sh
echo -e "one\nthree"
$
$ ./myscript.sh 
one
three
$
$ cat expected_output.txt
one
two
three
$
$ diff <(./myscript.sh) expected_output.txt
1a2
> two
$

As another example, let's say I want to check if two servers have the same list of RPMs installed. Rather than sshing to each server, writing each list of RPMs to separate files, and doing a diff on those files, I can just do the diff from my workstation:

$ diff <(ssh server1 'rpm -qa | sort') <(ssh server2 'rpm -qa | sort')
241c240
< kernel-2.6.18-92.1.6.el5
---
> kernel-2.6.18-92.el5
317d315
< libsmi-0.4.5-2.el5
727,728d724
< wireshark-0.99.7-1.el5
< wireshark-gnome-0.99.7-1.el5
$

There are more examples in the Advanced Bash-Scripting Guide at http://tldp.org/LDP/abs/html/process-sub.html.

community wiki

35

My favorite command is "ls -thor"

It summons the power of the gods to list the most recently modified files in a conveniently readable format.

community wiki

6 upvote
  flag
Reminds me of another, totally useless but also funny command: ls -bart -simpson -ruls. S, ICNR – filiprem Apr 24 '10 at 0:49
1 upvote
  flag
one could also say it like "ls -lotr" which apparently has something to do with Tolkien and Lord Of The Rings :) – ADEpt Aug 7 '10 at 17:37
28

More of a novelty, but it's clever...

Top 10 commands used:

$ history | awk '{print $2}' | awk 'BEGIN {FS="|"}{print $1}' | sort | uniq -c | sort -nr | head

Sample output:

 242 git
  83 rake
  43 cd
  33 ss
  24 ls
  15 rsg
  11 cap
  10 dig
   9 ping
   3 vi
1 upvote
  flag
Here's a shorter, faster version: history | awk 'BEGIN {FS="[ \t]+|\\|"} {print $3}' | sort | uniq -c | sort -nr | head – Dennis Williamson Jun 10 '10 at 4:17
25

^R reverse search. Hit ^R, type a fragment of a previous command you want to match, and hit ^R until you find the one you want. Then I don't have to remember recently used commands that are still in my history. Not exclusively bash, but also: ^E for end of line, ^A for beginning of line, ^U and ^K to delete before and after the cursor, respectively.

community wiki

2 upvote
  flag
I can never remember ^U for some reason. Isn't there a word delete delete shortcut too? – hoyhoy Sep 16 '08 at 1:36
1 upvote
  flag
^W deletes the word before the cursor. (Feel free to edit your answer with this.) – Jon Ericson Sep 16 '08 at 6:22
2 upvote
  flag
^R being so useful that it was mentioned in the question :) – Mark Baker Oct 27 '08 at 11:21
20

I often have aliases for vi, ls, etc. but sometimes you want to escape the alias. Just add a back slash to the command in front:

Eg:

$ alias vi=vim
$ # To escape the alias for vi:
$ \vi # This doesn't open VIM

Cool, isn't it?

community wiki

17

Here's a couple of configuration tweaks:

~/.inputrc:

"\C-[[A": history-search-backward
"\C-[[B": history-search-forward

This works the same as ^R but using the arrow keys instead. This means I can type (e.g.) cd /media/ then hit up-arrow to go to the last thing I cd'd to inside the /media/ folder.

(I use Gnome Terminal, you may need to change the escape codes for other terminal emulators.)

Bash completion is also incredibly useful, but it's a far more subtle addition. In ~/.bashrc:

if [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
fi

This will enable per-program tab-completion (e.g. attempting tab completion when the command line starts with evince will only show files that evince can open, and it will also tab-complete command line options).

Works nicely with this also in ~/.inputrc:

set completion-ignore-case on
set show-all-if-ambiguous on
set show-all-if-unmodified on
community wiki

17

I use the following a lot:

The :p modifier to print a history result. E.g.

!!:p

Will print the last command so you can check that it's correct before running it again. Just enter !! to execute it.

In a similar vein:

!?foo?:p

Will search your history for the most recent command that contained the string 'foo' and print it.

If you don't need to print,

!?foo

does the search and executes it straight away.

community wiki

2 upvote
  flag
Instead of using :p, you can also use magic-space: stackoverflow.com/questions/603696/… – Yoo Sep 13 '09 at 17:38
16

I have got a secret weapon : shell-fu.

There are thousand of smart tips, cool tricks and efficient recipes that most of the time fit on a single line.

One that I love (but I cheat a bit since I use the fact that Python is installed on most Unix system now) :

alias webshare='python -m SimpleHTTPServer'

Now everytime you type "webshare", the current directory will be available through the port 8000. Really nice when you want to share files with friends on a local network without usb key or remote dir. Streaming video and music will work too.

And of course the classic fork bomb that is completely useless but still a lot of fun :

$ :(){ :|:& };:

Don't try that in a production server...

3 upvote
  flag
@Donal: You should try it and report your findings. – Michael Foukarakis Sep 16 '10 at 7:04
12

You can use the watch command in conjunction with another command to look for changes. An example of this was when I was testing my router, and I wanted to get up-to-date numbers on stuff like signal-to-noise ratio, etc.

watch --interval=10 lynx -dump http://dslrouter/stats.html
community wiki

11 upvote
  flag
What in the world does 'watch' have to do with bash? – Artem Russakovskii Aug 4 '09 at 14:59
11
type -a PROG

in order to find all the places where PROG is available, usually somewhere in ~/bin rather than the one in /usr/bin/PROG that might have been expected.

community wiki

1 upvote
  flag
It will also tell you if it's a function or alias. If it's in multiple places in your PATH it will show each of them. – Dennis Williamson Jun 10 '10 at 4:25
11

I like to construct commands with echo and pipe them to the shell:

$ find dir -name \*~ | xargs echo rm
...
$ find dir -name \*~ | xargs echo rm | ksh -s

Why? Because it allows me to look at what's going to be done before I do it. That way if I have a horrible error (like removing my home directory), I can catch it before it happens. Obviously, this is most important for destructive or irrevocable actions.

community wiki

1 upvote
  flag
You might want to use find -print0 and xargs -0 to avoid problems with files and folders with white spaces in them. – neu242 Sep 22 '08 at 8:13
4 upvote
  flag
Why would you append "| ksh -s" when you could just remove the "echo"? – Yoo Sep 13 '09 at 17:27
10

When downloading a large file I quite often do:

while ls -la <filename>; do sleep 5; done

And then just ctrl+c when I'm done (or if ls returns non-zero). It's similar to the watch program but it uses the shell instead, so it works on platforms without watch.

Another useful tool is netcat, or nc. If you do:

nc -l -p 9100 > printjob.prn

Then you can set up a printer on another computer but instead use the IP address of the computer running netcat. When the print job is sent, it is received by the computer running netcat and dumped into printjob.prn.

community wiki

1 upvote
  flag
@Ted, watch is not available on all platforms though, like Solaris, Mac OS X, etc. @Porges, not sure what you mean. Can wget also listen on a port? – dreamlax Sep 16 '08 at 21:57
10

pushd and popd almost always come in handy

community wiki

10

One preferred way of navigating when I'm using multiple directories in widely separate places in a tree hierarchy is to use acf_func.sh (listed below). Once defined, you can do

cd --

to see a list of recent directories, with a numerical menu

cd -2

to go to the second-most recent directory.

Very easy to use, very handy.

Here's the code:

# do ". acd_func.sh"
# acd_func 1.0.5, 10-nov-2004
# petar marinov, http:/geocities.com/h2428, this is public domain

cd_func ()
{
  local x2 the_new_dir adir index
  local -i cnt

  if [[ $1 ==  "--" ]]; then
    dirs -v
    return 0
  fi

  the_new_dir=$1
  [[ -z $1 ]] && the_new_dir=$HOME

  if [[ ${the_new_dir:0:1} == '-' ]]; then
    #
    # Extract dir N from dirs
    index=${the_new_dir:1}
    [[ -z $index ]] && index=1
    adir=$(dirs +$index)
    [[ -z $adir ]] && return 1
    the_new_dir=$adir
  fi

  #
  # '~' has to be substituted by ${HOME}
  [[ ${the_new_dir:0:1} == '~' ]] && the_new_dir="${HOME}${the_new_dir:1}"

  #
  # Now change to the new dir and add to the top of the stack
  pushd "${the_new_dir}" > /dev/null
  [[ $? -ne 0 ]] && return 1
  the_new_dir=$(pwd)

  #
  # Trim down everything beyond 11th entry
  popd -n +11 2>/dev/null 1>/dev/null

  #
  # Remove any other occurence of this dir, skipping the top of the stack
  for ((cnt=1; cnt <= 10; cnt++)); do
    x2=$(dirs +${cnt} 2>/dev/null)
    [[ $? -ne 0 ]] && return 0
    [[ ${x2:0:1} == '~' ]] && x2="${HOME}${x2:1}"
    if [[ "${x2}" == "${the_new_dir}" ]]; then
      popd -n +$cnt 2>/dev/null 1>/dev/null
      cnt=cnt-1
    fi
  done

  return 0
}

alias cd=cd_func

if [[ $BASH_VERSION > "2.05a" ]]; then
  # ctrl+w shows the menu
  bind -x "\"\C-w\":cd_func -- ;"
fi
community wiki

10

Expand complicated lines before hitting the dreaded enter

  • Alt+Ctrl+eshell-expand-line (may need to use Esc, Ctrl+e on your keyboard)
  • Ctrl+_undo
  • Ctrl+x, *glob-expand-word

$ echo !$ !-2^ * Alt+Ctrl+e
$ echo aword someotherword * Ctrl+_
$ echo !$ !-2^ * Ctrl+x, *
$ echo !$ !-2^ LOG Makefile bar.c foo.h

&c.

community wiki

9

I've always been partial to:

ctrl-E # move cursor to end of line
ctrl-A # move cursor to beginning of line

I also use shopt -s cdable_vars, then you can create bash variables to common directories. So, for my company's source tree, I create a bunch of variables like:

export Dcentmain="/var/localdata/p4ws/centaur/main/apps/core"

then I can change to that directory by cd Dcentmain.

community wiki

1 upvote
  flag
More for your shortcut list: CTRL+K to delete everything from cursor to end of line, CTRL+U to delete everything before cursor, ALT+F/ALT+B to move one word forward/backward (or CTRL+left arrow/CTRL+right arrow). +1 for cdable_vars! – Philippe A. Jan 30 '12 at 17:39
8

pbcopy

This copies to the Mac system clipboard. You can pipe commands to it...try:

pwd | pbcopy

community wiki

7
$ touch {1,2}.txt
$ ls [12].txt
1.txt  2.txt
$ rm !:1
rm [12].txt
$ history | tail -10
...
10007  touch {1,2}.txt
...
$ !10007
touch {1,2}.txt
$ for f in *.txt; do mv $f ${f/txt/doc}; done
community wiki

7

Using 'set -o vi' from the command line, or better, in .bashrc, puts you in vi editing mode on the command line. You start in 'insert' mode so you can type and backspace as normal, but if you make a 'large' mistake you can hit the esc key and then use 'b' and 'f' to move around as you do in vi. cw to change a word. Particularly useful after you've brought up a history command that you want to change.

community wiki

7

Similar to many above, my current favorite is the keystroke [alt]. (Alt and "." keys together) this is the same as $! (Inserts the last argument from the previous command) except that it's immediate and for me easier to type. (Just can't be used in scripts)

eg:

mkdir -p /tmp/test/blah/oops/something
cd [alt].
community wiki

1 upvote
  flag
Also try pressing Alt-. more than once (or press down Alt, hold it there, press dot many times, and then release Alt) This is similar to pressing Ctrl-R more than once. – Yoo Sep 13 '09 at 17:34
7

String multiple commands together using the && command:

./run.sh && tail -f log.txt

or

kill -9 1111 && ./start.sh
1 upvote
  flag
if one fail, the other command wont be executed (fail fast, like in programmation) – Frederic Morin Apr 17 '09 at 9:27
1 upvote
  flag
The opposite is to use the logical or '||' in which the right hand side will only be executed if the left hand side is false. Example: <code>command_1 || command_2</code> – dala May 17 '10 at 13:26

Not the answer you're looking for? Browse other questions tagged or ask your own question.

asked

7 years ago

viewed

110460 times

active

4 years ago

Hot Network Questions

Technology Life / Arts Culture / Recreation Science Other
  1. Stack Overflow
  2. Server Fault
  3. Super User
  4. Web Applications
  5. Ask Ubuntu
  6. Webmasters
  7. Game Development
  8. TeX - LaTeX
  1. Programmers
  2. Unix & Linux
  3. Ask Different (Apple)
  4. WordPress Development
  5. Geographic Information Systems
  6. Electrical Engineering
  7. Android Enthusiasts
  8. Information Security
  1. Database Administrators
  2. Drupal Answers
  3. SharePoint
  4. User Experience
  5. Mathematica
  6. Salesforce
  7. ExpressionEngine® Answers
  8. more (13)
  1. Photography
  2. Science Fiction & Fantasy
  3. Graphic Design
  4. Movies & TV
  5. Seasoned Advice (cooking)
  6. Home Improvement
  7. Personal Finance & Money
  8. Academia
  9. more (9)
  1. English Language & Usage
  2. Skeptics
  3. Mi Yodeya (Judaism)
  4. Travel
  5. Christianity
  6. Arqade (gaming)
  7. Bicycles
  8. Role-playing Games
  9. more (21)
  1. Mathematics
  2. Cross Validated (stats)
  3. Theoretical Computer Science
  4. Physics
  5. MathOverflow
  6. Chemistry
  7. Biology
  8. more (5)
  1. Stack Apps
  2. Meta Stack Exchange
  3. Area 51
  4. Stack Overflow Careers
site design / logo © 2016 Stack Exchange Inc; user contributions licensed under cc by-sa 3.0 with attribution required
rev 2016.8.31.3939