bash -cオプションにおける変数$0について

最近、以下のようなbashコマンドを見かけました。

find /hoge/fuga -type f -iname "*.html" -exec bash -c 'cp -p "$0" tmp' {} \;

上記はディレクトリ/hoge/fuga内の.html拡張子のファイルを探し出して変数$0に格納し、ファイル名"tmp"としてコピーします。

でも、変数$0って確か実行されたコマンド名(または実行されたスクリプト名)を格納している変数じゃなかったっけ。

ということで、ちょっと調べてみました。

まずbashのcオプションについてmanより

-c string
If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0.

上記によると、stringの後に引数があれば、その引数は位置パラメータの$0から順番に代入されるとのこと。
つまり、こういうことです。

引数なし
bash -c 'echo $0'
bashc-1.png

引数あり
bash -c 'echo $0' dummy_argument
bashc-2.png

続いてfindコマンドのexecオプションについてmanより

-exec utility [argument ...] ;
True if the program named utility returns a zero value as its exit status. Optional arguments may
invoke find from a shell you may need to quote the semicolon if the shell would otherwise treat it
as a control operator. If the string ``{}'' appears anywhere in the utility name or the arguments
it is replaced by the pathname of the current file. Utility will be executed from the directory
from which find was executed. Utility and arguments are not subject to the further expansion of
shell patterns and constructs.

上記によると、{}はプレースホルダーの役割を果たし、findコマンドで見つかったファイル名に置き換えられます。

以上を踏まえて、もう一度冒頭のfindコマンドを見てみます。

find /hoge/fuga -type f -iname "*.html" -exec bash -c 'cp -p "$0" tmp' {} \;

1. bashのcオプションで、コマンド 'cp -p "$0" tmp' を引数つきで実行しています。この場合、{}が引数です。
2. {}は変数$0に代入されます。
3. {}はfindコマンドで見つかったファイル名に置き換えられます。なので最終的に変数$0にはfindコマンドで見つかったファイル名が代入されます。

検証
find /tmp/hoge -type f -iname "*.py" -exec bash -c 'echo "$0"' {} \;
bashc-3.png

以上。

Leave a Reply

Your email address will not be published. Required fields are marked *