事の発端
/etc/profile に以下のような記述がある
for i in /etc/profile.d/*.sh ; do
if [ -r "$i" ]; then
if [ "${-#*i}" != "$-" ]; then
. "$i"
else
. "$i" >/dev/null 2>&1
fi
fi
done
この "${-#*i}"
が何か分からなくて小1時間調べる羽目に...
"${-#*i}" とは
- 結論、
カレントシェルのフラグ情報が入っているシェル変数を変数展開し、前方一致除去したもの
分解して解釈する
$-
または ${-}
は カレントシェルが実行された時のオプションが入っている
$ echo "$-"
himBH
このオプションが何かというと(man bash 抜粋)
-h Remember the location of commands as they are looked up for execution. This is enabled by default.
-i If the -i option is present, the shell is interactive.
-m Monitor mode. Job control is enabled. This option is on by default for interactive shells on systems that support it (see JOB CONTROL above). All processes run in a separate process group. When a background job completes, the shell prints a line containing its exit status.
-B The shell performs brace expansion (see Brace Expansion above). This is on by default.
-H Enable ! style history substitution. This option is on by default when the shell is interactive.
# は変数展開の前方一致除去
$ x=foobar; echo "${x}"
foobar
$ x=foobar; echo "${x#f}" // 前方一致で f を除去
oobar
$ x=foobar; echo "${x#foo}" // 前方一致で foo を除去
bar
$ x=foobar; echo "${x#*b}" // 前方一致で *b を除去(*はワイルドカード)
ar
- これも man bash に書いてある
${parameter#word}
${parameter##word}
Remove matching prefix pattern. The word is expanded to produce a pattern just as in pathname expansion, and matched against the expanded value of parameter using the rules described under Pattern Matching below. If the pattern matches the
beginning of the value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the ``#'' case) or the longest matching pattern (the ``##'' case) deleted. If parameter is @ or *, the
pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the pattern removal operation is applied to each member of the array
in turn, and the expansion is the resultant list.
つまり "${-#*i}" とは
$ echo "${-}"
himBH
$ echo "${-#*i}"
mBH
/etc/profile では何をやりたいのか
- 再掲
for i in /etc/profile.d/*.sh ; do
if [ -r "$i" ]; then
if [ "${-#*i}" != "$-" ]; then
. "$i"
else
. "$i" >/dev/null 2>&1
fi
fi
done
if [ "${-#*i}" != "$-" ]; then
- カレントシェルが、インタラクティブかどうかを条件としている
- インタラクティブな場合は
true
- シェルスクリプトを実行
- インタラクティブではない場合は
false
- シェルスクリプトを実行するが、標準出力は捨てて、標準エラーを標準出力に出すようにしている
. "$i"
ちなみに、この . は、カレントシェルのプロセスを置換して、処理を実行する exec の省略形である- ちなみに、この
.
は、 ファイルを読み込んでカレントシェルでコマンドを実行するsource
の省略形である - man bash 抜粋
. filename [arguments] source filename [arguments] Read and execute commands from filename in the current shell environment and return the exit status of the last command executed from filename. If filename does not contain a slash, filenames in PATH are used to find the directory containing filename. The file searched for in PATH need not be executable. When bash is not in posix mode, the current directory is searched if no file is found in PATH. If the sourcepath option to the shopt builtin command is turned off, the PATH is not searched. If any argu- ments are supplied, they become the positional parameters when filename is executed. Otherwise the positional parameters are unchanged. If the -T option is enabled, source inherits any trap on DEBUG; if it is not, any DEBUG trap string is saved and restored around the call to source, and source unsets the DEBUG trap while it executes. If -T is not set, and the sourced file changes the DEBUG trap, the new value is retained when source completes. The return status is the status of the last command exited within the script (0 if no commands are executed), and false if filename is not found or cannot be read.