bash tips
きちんとまとめられた情報が少ないのでメモ。
bashの機能はemacsと共通する部分が多く、使われている用語やキーバインドも類似している。
以下で述べるキーバインドについて、C-xはCtrl+x、M-xはESC xまたはC-[ xを表す。
kill-ringを活用する
bashにはkill-ringと呼ばれる仕組みがあり、削除(cut)した文字列を再度貼り付ける(yank)ことができる。
たとえば、C-u(C-a C-kでもよい)を押すと現在入力しているコマンドラインがすべてcutされ、kill-ringに追加される。
一通り作業した後でC-yを押すと、C-uでcutしておいたコマンドラインを貼り直すことができる。
$ du --[C-u] => $ $ man du $ [C-y] => $ du -- $ du --max-depth=1 210104 ./tmp 4 ./.cache 12 ./.ssh 640 ./dotfiles 28 ./.emacs.d 210844 .
kill-ringをさらに遡るには、C-yに続けてM-yを繰り返し押せばよい。
なお、C-wを押すと直前のスペースまでcutすることができる。
ヒストリにあるコマンドを再実行する
!100のように入力することで、ヒストリにある100番目のコマンドを実行できる。
$ history | grep clone 257 git clone http://git.savannah.gnu.org/r/bash.git 419 git clone git://github.com/SimonWilkinson/openssh.git 880 history | grep clone $ !257 $ git clone http://git.savannah.gnu.org/r/bash.git
~/.bashrcなどでshopt -s histverifyしておけば、いきなり実行する代わりに展開結果を表示し確認することができる。
直前のコマンドをsudoする
!!は直前に実行したコマンドライン全体を表す。
したがって、sudo !!と打てば直前のコマンドをsudoして実行できる。
$ apt-get update E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied) E: Unable to lock directory /var/lib/apt/lists/ E: Could not open lock file /var/lib/dpkg/lock - open (13: Permission denied) E: Unable to lock the administration directory (/var/lib/dpkg/), are you root? $ sudo !! $ sudo apt-get update
こちらもshopt -s histverifyしておけば、実行する前に展開結果を確認することができる。
直前のコマンドラインを置換して実行する
!:gs/foo/bar/で直前のコマンドラインのfooをbarに置換して実行できる。
$ echo foo foo foo foo $ !:gs/foo/bar/ $ echo bar bar
これを行う場合は、shopt -s histverifyしておいたほうがよい。
なお、最初の一箇所のみの置換でよいなら、^foo^bar^を使うこともできる。
$ echo foo foo foo foo $ ^foo^bar^ $ echo bar foo
直前のコマンドの最後の引数を展開する
M-.を押せばよい。
$ mkdir newdirectory $ cd [M-.] => $ cd newdirectory
!!のように!$で参照することもできる。
戻りすぎたヒストリをリセットする
C-rで戻りすぎたヒストリをリセットし、最後のヒストリから検索をやり直すにはM->を押せばよい。
コマンドをエディタで編集してから実行する
C-x C-eでエディタを開き、保存した内容を実行させることができるが、使う場面は少ない。
しいて言えば、コピーしてきたコマンドリストを実行させる場面ぐらいであろう。
exit statusを表示する
~/.bashrcに次のように書いておくことで、コマンドが失敗したときのexit statusを端末に表示することができる。 ここでは、他の出力と区別するために背景色を赤にしている。
if [[ -n "$PS1" ]]; then
set -o pipefail
trap 'echo -e "\e[41mexit ${PIPESTATUS[*]}\e[0m"' ERR
fi
$ grep Usage: grep [OPTION]... PATTERN [FILE]... Try 'grep --help' for more information. exit 2
.bash_historyをコマンド実行ごとに更新する
~/.bashrcに次のように書いておくことで、通常シェルが終了するときに更新される.bash_historyをコマンド実行ごとに更新することができる。
if [[ -n "$PS1" ]]; then
shopt -s histappend
PROMPT_COMMAND='history -a'
fi
こうしておくことで、新たにシェルを起動した際、それまで別のシェルで打ち込まれていたヒストリが引き継がれるようになる。 また、同時に複数のシェルを起動している状況で、他のシェルで実行されたヒストリを手元のシェルに反映させるには次のコマンドを実行すればよい。
$ history -n
C-bで直前のディレクトリに戻る
~/.bashrcに次のように書いておくことで、C-bを押すとcd -が実行されるようにできる。
if [[ -n "$PS1" ]]; then
bind '"\C-b":"\ercd -\n"'
fi
bind -x '"\C-b":"cd -"'としてもほぼ同じ動作となるが、この場合プロンプト文字列が更新されないため上のようにする。
地味に便利。