Bash
目次
参考文献
- BashFAQ - Greg's Wiki これはすごい。特に以下の項目がためになる。
- BashPitfalls - Greg's Wiki bash の落とし穴。これも必見。
シェルスクリプト
- $# - 引数の個数なので、スクリプト名は含まない。(要は最後のインデックス)
- BASH Programming - Introduction HOW-TO
-
$'string'の形式で特殊文字を出力できる。$'\x30' = '0'など。 - $(cat file) とするなら、$(< file) の方が fork しないので速い。
配列
迷宮入りするかと思うほど理解するのが難しかった。。
- 初期化
array=(hoge fuga piyo)- インデックス指定
array=([2]=piyo [0]=hoge [1]=fuga)は↑と同じ配列。
- インデックス指定
- 参照
${array[1]} - 要素数
${#array[@]}
コマンド実行結果を 1 行ごとに配列に格納する
区切り文字を改行にしておかなければ、1 行ごとに格納されない。
IFS=$'\n' array=( $( ls -l ) )
配列に要素を追加
これもハマった…。一旦展開するのがポイント。
array=( "${array[@]}" "hoge" )
パラメータ展開
スクリプトを書く際には便利なものの、忘れがちなので書いておく。
${parameter#pattern} 前方最短一致部分を削除
${parameter##pattern} 前方最長一致部分を削除
${parameter%pattern} 後方最短一致部分を削除
${parameter%%pattern} 後方最長一致部分を削除
わかりにくいので使用例を示す。
- コマンドのパスから、そのコマンドがあるディレクトリのパスを得る
$ CMD_PATH=/usr/local/bin/hoge
$ echo ${CMD_PATH%/*}
/usr/local/bin
- ファイル名から、拡張子だけを取り出す
$ FILE_NAME=hoge-1.2.txt
$ echo ${FILE_NAME##*.}
txt
無限ループ
こいつで 1 セクション作るのはどうかと思うが…、他に見出しを付ける方法がないので。
while : do command done
while に真を渡す方法はいくつかあるが、bash 組み込みコマンド : が一番速いと思われる。
-
testコマンドに文字列を渡す (-n オプションは省略可能なので、文字列が渡されると必ず真が返る。) -
trueコマンド -
:コマンド
getopts
こういう関数の使い方ってすぐ忘れるので、定型文化しておこう。
GETOPT_ERR=0
while getopts "i:nh" opt; do
case $opt in
i) INTERVAL=$OPTARG;;
n) NOPRINT=1;;
h) usage; exit 0;;
?) GETOPT_ERR=1;;
esac
done
shift $(( $OPTIND - 1 ))
if [ $GETOPT_ERR -eq 1 ]; then
usage
exit 1
fi
trap
テストスクリプトなどを書く場合のゴミ掃除には必須だが、毎回使い方を忘れるのでメモ。
-
ARGが無い or'-'の場合は、初期値にリセット。 -
ARGが空文字列 "" の場合は、そのシグナルを無視する。 -
EXITは終了時、RETURNは関数や source の終了時。
Tips
コマンド実行後に任意の処理を行う
bash には PROMPT_COMMAND という環境変数があり、これに任意のコマンドをセットすると、 コマンド実行後に自動的に実行される。
例えば date をセットすると、コマンドを実行した日時が出力されるようになる。
kuro:~ kaz$ PROMPT_COMMAND=date 2009年 6月12日 金曜日 01時41分46秒 JST kuro:~ kaz$ ls Desktop Documents Downloads Library Movies Music Pictures Public Sites 2009年 6月12日 金曜日 01時41分50秒 JST
追記:
これ変数の名前から考えたら、コマンド実行後に実行されるんじゃなくて、
プロンプト表示前に実行されるんですな。結果はどちらでも同じだけど。
コマンドの終了ステータスを自動的に表示する
上記 PROMPT_COMMAND を使用して、コマンドがエラーで終了した場合などに終了ステータスを自動的に表示するようにする。 終了ステータスはコマンド実行直後に表示しないと次のコマンド実行により上書きされてしまうため、 うっかり操作により見逃してしまうことがあるが、自動的に表示することでこれを避けることができる。
~/.bashrc に以下を追加する。
function prompt_cmd {
local ret=$?
[ $ret -eq 0 ] || echo "exit $ret"
}
PROMPT_COMMAND="prompt_cmd; $PROMPT_COMMAND"
実行結果のサンプル:
$ echo hoge hoge $ cat hoge cat: hoge: そのようなファイルやディレクトリはありません exit 1 $ hoge bash: hoge: command not found exit 127
プロンプトに色を付ける
コマンドの出力の境界がわかりやすくなったり、 root になっているかどうかを色で判別できたり、かなり便利なこの機能。
.bashrc に以下を追記する。
col=33 # yellow
PS1="\[\033[${col}m[\u@\h \W]$ \[\033[0m\]"
^^^^^^^ ^ ^^^^^^^^^^^
色のエスケープシーケンス 色の設定をクリア
※当初、\e で書いていたが、カーソル位置と表示がズレる問題が発生したので修正した。
if [ -n "$PS1" ] && ! echo "$PS1" | grep -q 33 ; then
col="0;33"
PS1="\033[${col}m${PS1}\033[0m"
fi
※プロンプトが消えてしまう問題が発生したので、上記に修正した。
カラーリスト
Black 0;30 Dark Gray 1;30 Blue 0;34 Light Blue 1;34 Green 0;32 Light Green 1;32 Cyan 0;36 Light Cyan 1;36 Red 0;31 Light Red 1;31 Purple 0;35 Light Purple 1;35 Brown 0;33 Yellow 1;33 Light Gray 0;37 White 1;37
ある数を n ビットシフトした数
カーネルソースを読んでいると、512 << 16 などという数値が出てくることがあるが、
わざわざ計算機を持ち出さなくても、bash で計算できる。
$ echo $((512 << 16)) 33554432
bash で計算できるということは、vi を使っていても、終了せずに計算できる。
:!echo $((512 << 16)) 33554432
直前にいたディレクトリに戻る
OLDPWD 環境変数には、直前にいたディレクトリが格納されているので、
$ cd $OLDPWD
で戻ることができるが、cd に - を渡しても同様の結果となる。
$ cd -
深いディレクトリにいて、いったんホームディレクトリに行って帰ってくる場合などに便利だ。
よく使うコマンド
- 行頭にジャンプ:C-a 行末にジャンプ:C-e
- 行頭までキル:C-u 行末までキル:C-k
- 前単語をキル:C-w
- ヤンク:C-y
- 直前のコマンドの最後の引き数を挿入:M-. (これは便利)
- キャンセル:C-g
- 後方検索:C-r (これらは使い方が難しい)
- 前方検索:C-s
- 最終行へ:M-> (Poderosa では打ちにくい…)
起動時の設定ファイルの読み込み順序
- ログインシェルの場合 (ログイン時、su - user 時など)
-
/etc/profile- 最後に
/etc/profile.d/*.sh
- 最後に
-
~/.bash_profile- 最初に
~/.bashrc- 最初に
/etc/bashrc
- 最初に
- 最初に
-
よって、記載順にもよるが、設定順は以下の通り。
/etc/profile -> /etc/profile.d/*.sh -> /etc/bashrc -> ~/.bashrc -> ~/.bash_profile
- ログインシェルでない場合 (bash 実行時、su user 時など)
-
~/.bashrc- 最初に
/etc/bashrc- 最後に
/etc/profile.d/*.sh
- 最後に
- 最初に
-
よって、記載順にもよるが、設定順は以下の通り。
/etc/bashrc -> /etc/profile.d/*.sh -> ~/.bashrc
su 実行時に open() されるファイルは以下のコマンドで確認できる。
# strace -f -e trace=open -o su-bash.strace su - hagio
その他 (細かいこと)
-
exportは、その変数を子プロセスに引き継ぐ場合に用いる。
# cat test.sh echo $TEST # sh test.sh # TEST=hoge # sh test.sh # TEST=hoge sh test.sh hoge # export TEST # sh test.sh hoge
一度 export された変数は、値を書き換えても export されたままなので、 LANG などはその都度 export しなくても、実行するコマンドに渡される。
- Meta キーは、ESC キーあるいは Ctrl-[ で代用可。(Poderosa では有用)
- bash のビルトインコマンドの説明を見るには、help コマンドが良い。man だと検索が面倒。
My .bashrc
カスタマイズしたものに慣れてしまうと、素の状態にすぐに適応できなくなってしまうので良くないが、 それでも背に腹は代えられないモノたち。
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific aliases and functions
umask 022
HISTSIZE=10000
HISTFILESIZE=10000
function prompt_cmd {
local ret=$?
[[ $ret -eq 0 ]] || echo "exit $ret"
}
if [[ $PS1 ]]; then
col=33
PS1="\[\033[${col}m\][\u@\h \W]$ \[\033[0m\]"
alias C='LANG=C'
alias J='LANG=ja_JP.UTF-8'
alias ..='cd ..'
alias la='ls -a'
alias lla='ls -la'
alias llh='ls -lh'
alias c39='ssh 192.168.8.39'
alias c47='ssh 192.168.8.47'
alias c52='ssh 192.168.8.52'
alias s10='ssh 192.168.8.103'
alias s11='ssh 192.168.8.111'
alias r60='ssh 192.168.8.60'
alias l='less'
alias c='cat'
alias ?='echo exit $?'
complete -d cd
complete -c man
export GREP_COLOR='1;37;44'
alias g='grep --color=auto'
alias gr='g -r'
alias gi='g -i'
alias pg='pgrep -lf'
alias xgr='find . | xargs -P 4 grep --color=auto'
alias odx='od -Ax -tx1z'
#PROMPT_COMMAND="prompt_cmd; $PROMPT_COMMAND"
function edit {
vi $(which "$1")
}
fi