
Bash Shortcuts For Maximum Productivity - pooriaazimi
http://www.skorks.com/2009/09/bash-shortcuts-for-maximum-productivity/
======
unfletch
The things he calls "bang commands" are actually "event designators" (!!,
!blah), "word designators" ($) and "word modifiers" (:p). There are links to
docs for each at the bottom of this page:
[http://www.gnu.org/s/bash/manual/html_node/History-
Interacti...](http://www.gnu.org/s/bash/manual/html_node/History-
Interaction.html#History-Interaction)

I use them all the time, and anyone watching over my shoulder always asks what
that was. Learn !!, !$, and a few modifiers. You'll be glad you did.
Personally, I use !$ constantly (and variations like !-2$, which gets you the
last arg from 2 commands ago). The "h" modifier is handy, too. It's like
dirname for the word. Consider this example, where you copy a file to some
deep path, and then cd to that dir to continue working with the copy:

    
    
        $ cp foo.txt /some/really/long/destination/bar.txt
        $ cd !$:h
        $ # (do more with ./bar.txt)
    

The substitution (:s) and global substitution (:gs) modifiers are also useful:

    
    
        $ echo some args
        some args
        $ !!:s/some/more
        more args
    

(Also, note that his explanation of !* is actually incorrect. He says it
leaves off the last arg, but actually leaves out $0 (the command name). !* is
all of the previous command's arguments.)

Finally, one really useful thing he doesn't mention at all is brace expansion.
For example, these are equivalent:

    
    
        $ cp foo.conf foo.conf.bak
        $ cp foo.conf{,.bak}
    

[http://www.gnu.org/s/bash/manual/html_node/Brace-
Expansion.h...](http://www.gnu.org/s/bash/manual/html_node/Brace-
Expansion.html)

~~~
gbog
!! and !$ are alright, but I really dislike !blah, which is blindly
_executing_ the latest command starting with blah, whatever it is. The author
of the article should remove this "tip", it is bad advice, or at least make a
note that the !blah:p is highly preferable.

~~~
spiffytech
I prefer using Ctrl-r <blah>, which searches your history for 'blah' and puts
it on the command line. The preferable part is that you can keep hitting
Ctrl-r to see previous matches, which is often helpful since you don't want
the last match, but the second or third match.

------
pooriaazimi
A note to Mac users: Instead of Alt, you must press escape key. For example,
Esc+b moves the cursor backward one word in bash, but you'll probably want to
use option instead, so check 'Use option as meta key' in Terminal's settings
(under keyboard tab).

But if it's not very handy, you can set 'option+left arrow' to move cursor one
word backward. To do that, open Terminal's settings, go to keyboard and add a
shortcut for left arrow (with 'option' as modifier), and leave the action to
'send string to shell'. Then click on the textbox below that and press esc
(which should print '\033') and then 'b', or simply type '\033b' in the
textbox.

Just this simple shortcut makes Mac's Terminal 1000 times better.

~~~
ghshephard
Thanks very, very much. I'm embarrassed to admit I probably spend 3-5 hours a
day on a command line, and have just gotten used to set -o vi when I need to
bounce around long lines a lot. esc+f/esc+b were always awkward. It should
have occurred to me to just map the keys on Terminal.app!

In the interesting news department - Lion already has option left cursor/right
cursor already mapped to move a word forward and back - not sure if it was
there in snow leopard.

------
pkrumins
I am a huge fan of maximizing productivity in the shell. I wrote these three
articles a while ago:

Bash emacs-like keyboard shortcuts:

[http://www.catonmat.net/blog/bash-emacs-editing-mode-
cheat-s...](http://www.catonmat.net/blog/bash-emacs-editing-mode-cheat-sheet/)

Bash vi-like keyboard shortcuts:

[http://www.catonmat.net/blog/bash-vi-editing-mode-cheat-
shee...](http://www.catonmat.net/blog/bash-vi-editing-mode-cheat-sheet/)

Definitive bash guide to command line history:

[http://www.catonmat.net/blog/the-definitive-guide-to-bash-
co...](http://www.catonmat.net/blog/the-definitive-guide-to-bash-command-line-
history/)

And they all come with cheat sheets. See downloads box at the bottom of each
post for download links.

~~~
dave1010uk
Great articles. I'm just starting to get into the hang of vi. I'm giving vi-
mode in bash a go (with "set -o vi") but there doesn't seem to be any
indication of when I'm in command/insert mode. Is there any way to see this?

~~~
mun2mun
There is a workaround in zsh [http://superuser.com/questions/151803/how-do-i-
customize-zsh...](http://superuser.com/questions/151803/how-do-i-customize-
zshs-vim-mode)

------
gaving
I'm a zsh user, but here's a couple of things I find pretty invaluable:-

    
    
        bindkey '^Q' push-line
    

The 'push-line' widget allows you to quickly type another command and will
restore the previous one once you've entered it.

    
    
        # re-run the previous command with sudo
        rerun-with-sudo () {
          LBUFFER="sudo !!"
          zle accept-line
        }
        zle -N rerun-with-sudo
        bindkey '^Xx' rerun-with-sudo
    

Re-run the previous command prefixed with sudo by typing ^X then x.

And:-

    
    
        # build git clone command from clipboard
        git-clone-clipboard() {
            REPO_URL="$($CLIPBOARD)"
            REPO_BASE_NAME=${$(basename $REPO_URL)%.git}
            LBUFFER="nocorrect git clone $REPO_URL $REPO_BASE_NAME"
        }
        zle -N git-clone-clipboard
        bindkey "^Xg" git-clone-clipboard
    

^Xg prefixes a git url with "git clone" and fills out the command line.

Couple similar things for wget, youtube-dl here:
<https://github.com/gaving/dotfiles/blob/master/.zsh/config>

~~~
pmr_
If I have a URL in my clipboard and want to prefix it I use:

    
    
        git clone `xclip -o`
    

Much simpler and no customization needed.

~~~
gaving
uh, why wouldn't you just actually paste the url into your terminal at that
point instead of typing `xclip -o`?

and yeah, typing the actual command into the terminal is always going to be
'simpler'

------
andrewflnr
One of my favorite bash shortcuts is binding the up arrow to history-search-
backward. This is the first page I found that concisely explains how; the
variant in the second comment is the one actually in my .bashrc:

[http://hints.macworld.com/article.php?story=2003102617423686...](http://hints.macworld.com/article.php?story=20031026174236860)

So if you've typed `verylongcommand` some indeterminate time in the past, you
can probably just type "ver<up>", and you'll have it. Very convenient.

~~~
irahul
A quick look at the article shows it's binding history search. It's already
bind to ctrl-r - you can do a ctrl-r, type a few letters of the long commands,
and keep doing a ctrl-r till you find the right match.

Apart from additional bind your setup requires, arrow keys are near impossible
to touch type. Even if you can touch type them, that means taking your hands
off the home row, and positioning them again.

~~~
bostonvaulter2
I think with the parent's setup you can do ver<C-p> to get the same effect.

------
arckiearc
Great tips. !! is a nice timesaver when you've forgotten to prepend sudo to a
command:

    
    
      $ /etc/init.d/rabbitmq-server restart
      Failed, need root access
      $ sudo !!
      Success
    

cd - is also quite cool, it takes you to the previous working directory.

    
    
      $ pwd
      /some/really/long/path/goes/here
      $ cd /var/log/app
      Work in this directory for a while, then go to previous dir
      $ cd -
      $ pwd
      /some/really/long/path/goes/here

~~~
gommm
I have the following in my zshrc for sudo. It adds sudo at the beginning of
the current line or writes sudo !! if the current line is empty. I've aliased
it to alt+s

    
    
        run-with-sudo() {
          if [[ -z $LBUFFER ]]; then
            LBUFFER="sudo !!";
          else
            LBUFFER="sudo $LBUFFER";
          fi
        };
        zle -N run-with-sudo;
        bindkey '\es' run-with-sudo

~~~
arckiearc
Nice little timesaver for such a common task, I'd just been doing the
following (with vi editing on) but yours is much easier:

    
    
      esc-0-i-sudo

~~~
woogley
It may not be less keystrokes, but for what it's worth, I find using shift+i
is easier than 0-i

~~~
arckiearc
Didn't know about that one, thanks!

------
kleiba
It's well known that !! is a sweet little helper in case where you forgot to
sudo a command. However, I find that for those cases I usually use `Up-arrow
CTRL-A` to get the previous command and then go to the beginning of the line
where I can type `sudo`. Is there any reason to prefer the !! variant?

~~~
ajross
If you're on a non-interactive terminal. Some of us didn't throw out our
teletypes. Also: when rooting boxes often one lacks space in the exploit
payload to set up the tty line discipline.

------
Azrathud
Most of the commands there can be replaced with vi keybindings.

That is, set -o vi

You can type that directly into your terminal for use just in one session or
in your .bashrc

Type <C-]> or <Esc> just like in vim to escape into "command" mode. Most
command mode commands work. E.g. '^' goes to the beginning of the line '$'
goes to the end. 'i' sets bash back into insert mode.

------
dongsheng
I use `..` to go upper directory, `...` to go up two levels, I added this to
bashrc:

    
    
      str='..'
      level='./../'
      for i in `seq 1 10`;
      do
          eval "alias '$str=cd $level'"
          level=$level'../'
        str=$str'.'
      done
    

Note, seq is not available in Mac, should use jot instead.

~~~
imurray
There's no need for seq or jot. In bash you can replace `seq 1 10` with
{1..10}. Or {01..10} if you want zero padding when using $i to label files.

I use an function called "up" that takes an optional integer argument to go up
a certain number of levels. It won't necessarily be faster, but somehow I
prefer it to typing lots of dots in a row:

    
    
       function up () { if test $# = 1 ; then s=$( printf "%$1s" ); s=${s// /..\/}; cd $s ; else cd .. ; fi; }

~~~
dongsheng
Thanks for pointing out that

------
dhugiaskmak
I've been using this[1] page as a cheatsheet for readline commands.

[1] [http://jan.tomka.name/sites/default/files/readline-
commands....](http://jan.tomka.name/sites/default/files/readline-
commands.html)

------
secoif
commandline and vim have easily got the most powerful, yet the most rage-
inducing key mappings – ever.

The worst, and most easily rectifiable aspect is the way command pairs (eg
move back/forward a word) require two totally separate commands (esc + b/esc +
f) instead of having one command + a generic 'reverse' meta key.

In the future I hope someone has the balls to do away with this legacy tripe
and popularise some more Donald-Normanesque keyboard shortcuts.

~~~
spacemanaki
I'm not sure if you're just trolling, but I don't understand your complaints
at all. What would your "Donald-Normanesque keyboard shortcuts" even look
like? In Windows the arrow keys act pretty similar, don't they? left-arrow,
right-arrow for moving by character, Ctrl-left-arrow, Ctrl-right-arrow for
moving by word. Windows is about as Donald-Normanesque as you can get...

The bash shortcuts are from readline, which (in this case, but by default?)
are the same as Emacs. C-f,C-b for moving by character, M-f,M-b for moving by
word. C-n,C-p for next and previous line. I think there's a vi switch for
readline which would allow you to have vi style shortcuts in bash. This is
nice, because it means you have one set of keyboard shortcuts in your editor
and shell. Emacs users in OS X get this in any text box (at least any that
supports the same defaults as the system, I'm spitting at you MS
Outlook/Entourage). I'm sure you could set something up in other windows
systems, like GNOME or KDE.

Sure the keyboard shortcuts might be cryptic, but any keyboard shortcuts will
be. Don't slag something just because you don't know the history and
background behind the choices.

------
montecarl
Sometimes I find myself typing out a long command and then deciding that I
don't want to run it quite yet. Normally I just hit C-c run some other command
first and then copy paste the long command. Surely there is someway to put the
long command in history?

~~~
gnubardt
Comment it out (put a # at the front), unless your shell is set to ignore
commented lines.

~~~
montecarl
This works great! There is even a shortcut: M-#

~~~
lukeschlather
You said copy-paste - are you using the OS copy-paste or readline's kill ring?
C-a C-k is pretty fast, and then can be retrieved with C-y.

~~~
montecarl
This is another great solution. As a vim user I haven't much looked into the
emacs keybindings in readline. I'll have to read up. Also the terminology was
a little confusing. I didn't realize that killing a line was the same as
"cutting".

~~~
lukeschlather
Yeah, and of course this does mean you have to be a little careful with
M-backspace (backward-kill-word in Emacs), since it will change your kill
ring.

But on other hand M-backspace can be useful too if you want to get just part
of a line, you can move the cursor to where you want, then M-backspace through
words to grab it - if you do M-backspace repeatedly the entire string is
pulled into the kill ring until you stop pressing M-BS.

------
tedkalaw
I'm not an Emacs user, but aren't a lot of the text-editing shortcuts straight
from Emacs?

~~~
aerique
Yup, but you can also put Bash in a vi mode. Some else will to chip in with
the exact incantation, since I'm on my phone now.

~~~
pyre

      set -o emacs
    

or

    
    
      set -o vi

------
veyron
Cheatsheet for emacs mode (which is what the article presumes):
[http://www.catonmat.net/download/readline-emacs-editing-
mode...](http://www.catonmat.net/download/readline-emacs-editing-mode-cheat-
sheet.pdf)

------
super_mario
These assume you use default emacs mode. If you are vi/vim user then set -o vi
will allow you to get immediately productive in bash, using vi motion commands
to edit the command line.

------
Ideka
Try Alt-*

    
    
        ls /etc/p<Alt-*>

------
dramaticus3
the best bash shortcut you could do

    
    
        # ln -s /usr/local/plan9/bin/rc /bin/bash

