
シェルスクリプトを作る上で、以外と便利なのがsetコマンド。
オプションごとに関連性が薄いので覚えにくいのだが、使いこなせれば結構役に立つ事が多いコマンドだ。
今回は、そんなsetコマンドで覚えておきたい使い方についてを紹介する。
1.引数・オプションなしで実行(変数の一覧を表示する)
setコマンドは、引数無しで実行すると現在設定されている変数の一覧を表示させることが出来る。
bash
set
shell[root@test-centos7 ~]# set BASH=/bin/bash BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath BASH_ALIASES=() BASH_ARGC=() BASH_ARGV=() BASH_CMDS=() BASH_LINENO=() BASH_SOURCE=() BASH_VERSINFO=([0]="4" [1]="2" [2]="45" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu") BASH_VERSION='4.2.45(1)-release' COLUMNS=112 DIRSTACK=() EUID=0 GROUPS=() HISTCONTROL=ignoredups HISTFILE=/root/.bash_history HISTFILESIZE=1000 HISTSIZE=1000 HOME=/root HOSTNAME=test-centos7 HOSTTYPE=x86_64 ID=0 IFS=$' \t\n' LANG=ja_JP.UTF-8 LESSOPEN='||/usr/bin/lesspipe.sh %s' LINES=36 LOGNAME=root LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:' MACHTYPE=x86_64-redhat-linux-gnu MAIL=/var/spool/mail/root MAILCHECK=60 OPTERR=1 OPTIND=1 OSTYPE=linux-gnu PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin:/root/bin PIPESTATUS=([0]="0") PPID=23637 PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"' PS1='[\u@\h \W]\$ ' PS2='> ' PS4='+ ' PWD=/root SELINUX_LEVEL_REQUESTED= SELINUX_ROLE_REQUESTED= SELINUX_USE_CURRENT_RANGE= SHELL=/bin/bash SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor SHLVL=1 SSH_CLIENT='XXX.XXX.XXX.XXX 52074 22' SSH_CONNECTION='XXX.XXX.XXX.XXX 52074 YYY.YYY.YYY.YYY 22' SSH_TTY=/dev/pts/0 TERM=xterm UID=0 USER=root XDG_RUNTIME_DIR=/run/user/0 XDG_SESSION_ID=8459 _=PATH colors=/root/.dircolors [root@test-centos7 ~]# [root@test-centos7 ~]# set | grep TEST [root@test-centos7 ~]# TEST=1234 [root@test-centos7 ~]# set | grep TEST TEST=1234
2.実行するコマンドをコンソール上に出力する
「set -v」で実行するコマンドを、「set -x」でそのコマンドの変数等を展開した状態でコンソール上に表示させることが出来る。
(以下例の「printf ~」というのはPS1の表示を行っているもの)
shell[root@test-centos7 ~]# echo $HOME /root [root@test-centos7 ~]# [root@test-centos7 ~]# set -v printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}" [root@test-centos7 ~]# echo $HOME echo $HOME /root printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}" [root@test-centos7 ~]# set +v set +v [root@test-centos7 ~]# [root@test-centos7 ~]# set -x ++ printf '\033]0;%s@%s:%s\007' root test-centos7 '~' [root@test-centos7 ~]# echo $HOME + echo /root /root ++ printf '\033]0;%s@%s:%s\007' root test-centos7 '~' [root@test-centos7 ~]# set +x + set +x
ちなみに、無効にする際はオプション値を「+」を使って記述してあげると良い。
3.シェルスクリプトの構文チェックだけを行わせる
シェルスクリプト内に「set -n」もしくは「set -o noexec」を記述することで、スクリプト実行時に構文チェックだけ行わせて、その中の処理を実行させないようにすることが出来る。
例えば、以下のように「set -n」を記述していないスクリプトを実行するとコマンドが実行されてしまうが、記述しているスクリプトだと構文チェックだけを行ってくれている。
shell
[root@test-centos7 ~]# ls /tmp/test
[root@test-centos7 ~]# cat /work/test27.sh
#!/bin/bash
#set -n
mkdir "/tmp/test/test1234"
for fichier in `ls`
do
if [[ -f "$fichier ]]; then
echo "$fichier"
fi
done
[root@test-centos7 ~]# cat /work/test28.sh
#!/bin/bash
set -n
mkdir "/tmp/test/test5678"
for fichier in `ls`
do
if [[ -f "$fichier ]]; then
echo "$fichier"
fi
done
[root@test-centos7 ~]# bash /work/test27.sh
/work/test27.sh: 行 7: 一致する `"' を探索中に予期しないファイル終了 (EOF) です
/work/test27.sh: 行 10: 条件単項演算子に予期しない引数です
/work/test27.sh: 行 10: 構文エラー: 予期しないファイル終了 (EOF) です
[root@test-centos7 ~]# bash /work/test28.sh
/work/test28.sh: 行 7: 一致する `"' を探索中に予期しないファイル終了 (EOF) です
/work/test28.sh: 行 10: 条件単項演算子に予期しない引数です
/work/test28.sh: 行 10: 構文エラー: 予期しないファイル終了 (EOF) です
[root@test-centos7 ~]# ls /tmp/test
test1234
4.シェルスクリプト内で実行された処理が正常終了しない場合、処理を停止させる
シェルスクリプト内で「set -e」もしくは「set -o errexit」と記述することで、一部の処理を除いて、スクリプト内の実行コマンドが正常終了しなかった場合にスクリプトを即終了させる事が出来る。
例えば、以下の例の場合だと「set -e」が無いとエラーになった後の処理も実行されてしまうが、「set -e」が記述されていればそこで処理が止まっている。
shell
[root@test-centos7 ~]# ls -la /tmp/TEST
ls: /tmp/TEST にアクセスできません: そのようなファイルやディレクトリはありません
[root@test-centos7 ~]# cat /work/test29.sh
#!/bin/bash
#set -e
mkdir /tmp/TEST1234/TEST
mkdir /tmp/TEST1234/TEST/1234
mkdir /tmp/TEST1234/TEST/5678
[root@test-centos7 ~]# cat /work/test30.sh
#!/bin/bash
set -e
mkdir /tmp/TEST1234/TEST
mkdir /tmp/TEST1234/TEST/1234
mkdir /tmp/TEST1234/TEST/5678
[root@test-centos7 ~]#
[root@test-centos7 ~]# bash /work/test29.sh
mkdir: ディレクトリ `/tmp/TEST1234/TEST' を作成できません: そのようなファイルやディレクトリはありません
mkdir: ディレクトリ `/tmp/TEST1234/TEST/1234' を作成できません: そのようなファイルやディレクトリはありません
mkdir: ディレクトリ `/tmp/TEST1234/TEST/5678' を作成できません: そのようなファイルやディレクトリはありません
[root@test-centos7 ~]# bash /work/test30.sh
mkdir: ディレクトリ `/tmp/TEST1234/TEST' を作成できません: そのようなファイルやディレクトリはありません
ただ、先ほども記述したように一部の処理(ループ内の処理だったり、三項演算子内だったりetc)については、正常終了でなくてもそのままスクリプトは実行されてしまうので注意が必要。
5.パス名の展開を無効にする
「set -f」もしくは「set -o noglob」を実行すると、シェルで「*(アスタリスク)」などでのワイルドカードでの展開を無効にする事ができる。
shell[root@test-centos7 ~]# ls /tmp/* /tmp/* /tmp/date_file /tmp/tar_test.tar /tmp/tar_test.tar.gz /tmp/aaaaaa.log /tmp/dddddd.log /tmp/tar_test.tar.bz2 /tmp/test1 /tmp/test: test1234 /tmp/test12345678: /tmp/test2: [root@test-centos7 ~]# [root@test-centos7 ~]# set -f [root@test-centos7 ~]# ls /tmp/* /tmp/* [root@test-centos7 ~]# set +f [root@test-centos7 ~]# ls /tmp/* /tmp/* /tmp/date_file /tmp/tar_test.tar /tmp/tar_test.tar.gz /tmp/aaaaaa.log /tmp/dddddd.log /tmp/tar_test.tar.bz2 /tmp/test1 /tmp/test: test1234 /tmp/test12345678: /tmp/test2:
6.ブレース展開を無効にする
「set +B」もしくは「set +o braceexpand」で、シェルのブレース展開を無効にする事ができる。
shell[root@test-centos7 ~]# echo abc{123,456,789}def abc123def abc456def abc789def [root@test-centos7 ~]# [root@test-centos7 ~]# set +B [root@test-centos7 ~]# echo abc{123,456,789}def abc{123,456,789}def
7.リダイレクト時の上書きを無効にする
「set -C」および「set -o noclobber」を実行すると、リダイレクト時のファイルへの上書き(追記はできる)を無効にすることが出来る。
(ただし、「>|」を用いると上書き可能になっている)
shell[root@test-centos7 ~]# echo 0 > /tmp/aaaaa [root@test-centos7 ~]# cat /tmp/aaaaa 0 [root@test-centos7 ~]# [root@test-centos7 ~]# echo 01 > /tmp/aaaaa [root@test-centos7 ~]# cat /tmp/aaaaa 01 [root@test-centos7 ~]# [root@test-centos7 ~]# set -C [root@test-centos7 ~]# [root@test-centos7 ~]# echo 0123 > /tmp/aaaaa -bash: /tmp/aaaaa: 存在するファイルを上書きできません [root@test-centos7 ~]# echo 0123 >> /tmp/aaaaa [root@test-centos7 ~]# cat /tmp/aaaaa 01 0123 [root@test-centos7 ~]# [root@test-centos7 ~]# echo 0123 >| /tmp/aaaaa [root@test-centos7 ~]# cat /tmp/aaaaa 0123
8.引数を指定し直す
setコマンドにオプション無しで引数を渡すと、スクリプトの引数を設定し直す事が出来る。
shell
[root@test-centos7 ~]# set 1234 5678
[root@test-centos7 ~]# echo $2
5678
[root@test-centos7 ~]# echo $1
1234
[root@test-centos7 ~]#
[root@test-centos7 ~]# cat /work/test31.sh
#!/bin/bash
set abcdef ghijk 12345
echo $1
echo $3
echo $2
[root@test-centos7 ~]#
[root@test-centos7 ~]# bash /work/test31.sh
abcdef
12345
ghijk
[root@test-centos7 ~]# bash -x /work/test31.sh
+ set abcdef ghijk 12345
+ echo abcdef
abcdef
+ echo 12345
12345
+ echo ghijk
ghijk
9.現在のオプション状態を確認する
setコマンドで設定したオプション値を確認する場合、ただ「set -o」と実行することでその一覧を確認出来る。
shell[root@test-centos7 ~]# set -o allexport off braceexpand on emacs on errexit off errtrace off functrace off hashall on histexpand on history on ignoreeof off interactive-comments on keyword off monitor on noclobber on noexec off noglob off nolog off notify off nounset off onecmd off physical off pipefail off posix off privileged off verbose off vi off xtrace off