Bash Shortcuts For Maximum Productivity
skorks.com
skorks.com
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... $ alias select='sqlcommand -s "select !*"'
would translate: $ select * from tablename
to: $ sqlcommand -s "select * from tablename"
(Note: I may be getting the specifics messed up as it's been a couple of years since I looked at the implementation, but the general idea is there.)http://www.gnu.org/s/bash/manual/html_node/Commands-For-Hist...
M-C-y (yank-nth-arg) works similarly for the first argument of the previous command, but without cycling through all previous commands.
After the more complex modifiers like !$:p, :e, :s/old/new/, etc, before hitting Return I often use M-C-e (shell-expand-line) just to check I got it right.
http://www.gnu.org/s/bash/manual/html_node/Miscellaneous-Com...
You post inspired me to quickly create two (hopefully) handy bash functions:
# Create a backup of the given file(s)
# USAGE: bk file1 file2 file3
# -> result: file1.bak file2.bak file3.bak
bk() {
for file in "$@"
do
cp $file{,.bak}
done
}
# Restores the file from backup
# USAGE: rbk file.bak OR rbk file
# -> result: replaces file with file.bak
rbk() {
if [[ $1 == *.bak ]]
then
backup_file=$1
old_file=${backup_file:0:$((${#backup_file}-4))}
else
old_file=$1
backup_file=${old_file}".bak"
fi
read -p "Replace the old backup? (y/N) " -n 2
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
`cp $backup_file $old_file`
fi
}
I've put them in my newly created .functions file (https://github.com/pooriaazimi/dotfiles/blob/master/.functio...).To enable it, edit your .inputrc (this is part of readline) and add this:
$if Bash
Space: magic-space
$endif cd () {
if [[ -f $1 ]]
then
builtin cd $1:h
else
builtin cd "$@"
fi
}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.
I also have 'option+right arrow' mapped to move cursor one word forward (use the same instructions as above, substituting 'f' for 'b').
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.
http://stackoverflow.com/questions/196357/making-iterm-to-tr...
I still don't like it since I am so used to hitting the Apple key in emacs, but it beats having to use Esc+<letter>
Bash emacs-like keyboard shortcuts:
http://www.catonmat.net/blog/bash-emacs-editing-mode-cheat-s...
Bash vi-like keyboard shortcuts:
http://www.catonmat.net/blog/bash-vi-editing-mode-cheat-shee...
Definitive bash guide to command line history:
http://www.catonmat.net/blog/the-definitive-guide-to-bash-co...
And they all come with cheat sheets. See downloads box at the bottom of each post for download links.
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
git clone `xclip -o`
Much simpler and no customization needed.and yeah, typing the actual command into the terminal is always going to be 'simpler'
http://hints.macworld.com/article.php?story=2003102617423686...
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.
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.
$ /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 run-with-sudo() {
if [[ -z $LBUFFER ]]; then
LBUFFER="sudo !!";
else
LBUFFER="sudo $LBUFFER";
fi
};
zle -N run-with-sudo;
bindkey '\es' run-with-sudo esc-0-i-sudoI think it's faster than a cycle of :p, verify it's what you want and then reexec. It's also mentally less taxing (albeit a tiny amount). But summed over a day of shell work, I think it makes a difference.
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.
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.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; }[1] http://jan.tomka.name/sites/default/files/readline-commands....
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.
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.
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.
set -o emacs
or set -o viI am a dyed in the wool vim enthusiast, but when it comes to command line bindings, emacs' bindings are more convenient.
ls /etc/p<Alt-*> # ln -s /usr/local/plan9/bin/rc /bin/bash