スクリプトに渡す引数でワイルドカードが展開され、困る
Q:ワイルドカードを展開しないまま、スクリプトに渡すことはできるか?
A:未解決。シングルクオートでくくってもうまくいかない(cygwin, Linux)。
要件:
スクリプトのなかでfindを使いたい。
このとき、-name オプションで、ファイルパターンを指定したい。
このとき、ファイルパターンにワイルドカードを使いたい。
予想:
ワイルドカードつかっててもシングルクオートでくくっていれば、
展開されないままコマンド(やスクリプト)に渡るのだとばかり思っていた。
つまり、コマンド(やスクリプト)にワイルドカードを
文字列として渡したい場合はシングルクオートでくくれば
よいのだと思っていた。
実際:
\*.javaにマッチするファイルがあるディレクトリで
スクリプトを実行すると、スクリプトの引数で'*.java'としても、
$変数値としては展開後の値が入っている。詳しくは下の記録を。
そのため、値が期待どおりにはfindコマンドに渡らず、
findからエラーが返る。
結果を要約すると:
マッチするファイルがあるディレクトリで実行。シングルクオートあり。→ 失敗
マッチするファイルがあるディレクトリで実行。シングルクオートなし。→ 失敗
マッチするファイルがないディレクトリで実行。→ うまくいく
とりあえず:
ワイルドカードが展開されて困るのは、スクリプト実行ディレクトリに
パターンにマッチするファイルがある場合のみ。とりあえず今は、
ひとつ上位のディレクトリで *.java を含まないディレクトリから
実行してしのぐ。しのぎますが、気持ち悪い。
ついでに、同じように、*.javaでヒットする階層で find . -name '*.java'
を実行しても、ちゃんとうまくいく。→ find には、
ワイルドカードが展開されずに渡っているということ。
Linuxは↓で試した。
[test]$ bash -version
GNU bash, version 2.05b.0(1)-release (i386-redhat-linux-gnu)
Copyright (C) 2002 Free Software Foundation, Inc.
cygwinは↓で試した。
/usr/bin bash$bash -version
GNU bash, version 2.05b.0(1)-release (i686-pc-cygwin)
Copyright (C) 2002 Free Software Foundation, Inc.
cygwinで試した時の記録
findsh.sh
#!/bin/sh echo find + grep result: find $1 -name $2 | xargs grep -n $3 echo '$1 =' $1 echo '$2 =' $2 echo '$3 =' $3
マッチするファイルがあるディレクトリで実行。シングルクオートあり。→ 失敗
~/tmp/find_test bash$ls -l total 3 -rwxr-xr-x 1 Administ なし 7 Feb 16 17:04 abc.java* -rwxr-xr-x 1 Administ なし 7 Feb 16 17:04 abc.java~* -rw-r--r-- 1 Administ なし 0 Feb 16 14:09 abc.txt -rwxr-xr-x 1 Administ なし 15 Feb 16 17:04 xyz.java* -rw-r--r-- 1 Administ なし 0 Feb 16 12:15 xyz.java~ -rw-r--r-- 1 Administ なし 0 Feb 16 12:15 xyz.txt ~/tmp/find_test bash$~/scripts/findsh.sh . '*.java' final find + grep result: find: paths must precede expression ← findの怒り Usage: find [path...] [expression] $1 = . $2 = abc.java xyz.java ← 該当ファイルが展開されて変数に入っている $3 = final ~/tmp/find_test bash$
マッチするファイルがあるディレクトリで実行。シングルクオートなし。→ 失敗~/tmp/find_test bash$ls -l total 3 -rwxr-xr-x 1 Administ なし 7 Feb 16 17:04 abc.java* -rwxr-xr-x 1 Administ なし 7 Feb 16 17:04 abc.java~* -rw-r--r-- 1 Administ なし 0 Feb 16 14:09 abc.txt -rwxr-xr-x 1 Administ なし 15 Feb 16 17:04 xyz.java* -rw-r--r-- 1 Administ なし 0 Feb 16 12:15 xyz.java~ -rw-r--r-- 1 Administ なし 0 Feb 16 12:15 xyz.txt ~/tmp/find_test bash$~/scripts/findsh.sh . *.java final find + grep result: ← 該当なしという結果 $1 = . $2 = abc.java ← 展開・ソートされた1番目が入っている $3 = xyz.java← 展開・ソートされた2番目が入っているマッチするファイルがないディレクトリで実行。→ うまくいく
~/tmp/find_test bash$cd .. ~/tmp bash$ls -l total 0 drwxr-xr-x+ 2 Administ なし 0 Feb 16 09:53 cat_test/ drwxr-xr-x+ 2 Administ なし 4096 Feb 16 17:04 find_test/ drwxr-xr-x+ 3 Administ なし 4096 Feb 16 12:09 rgrep_test/ ~/tmp bash$~/scripts/findsh.sh . '*.java' final find + grep result: ./find_test/abc.java:1:final ./find_test/xyz.java:5:final $1 = . $2 = *.java $3 = final
#!/bin/sh echo find + grep result: find $1 -name $2 | xargs grep -n $3 echo '$1 =' $1 echo '$2 =' $2 echo '$3 =' $3マッチするファイルがあるディレクトリで実行。シングルクオートあり。→ 失敗
[soot@soot-linux find_test]$ ls -l 合計 8 -rw-rw-r-- 1 soot soot 6 2月 16 16:34 abc.java -rw-rw-r-- 1 soot soot 0 2月 16 15:26 abc.txt -rw-rw-r-- 1 soot soot 7 2月 16 16:34 xyz.java -rw-rw-r-- 1 soot soot 0 2月 16 15:26 xyz.txt [soot@soot-linux find_test]$ ~/scripts/findsh.sh . '*.java' final find + grep result: find: paths must precede expression ← find の怒り Usage: find [path...] [expression] $1 = . $2 = abc.java xyz.java ← ワイルドカード展開+ソート $3 = final [soot@soot-linux find_test]$マッチするファイルがあるディレクトリで実行。シングルクオートなし。→ 失敗
[soot@soot-linux find_test]$ ls -l 合計 8 -rw-rw-r-- 1 soot soot 6 2月 16 16:34 abc.java -rw-rw-r-- 1 soot soot 0 2月 16 15:26 abc.txt -rw-rw-r-- 1 soot soot 7 2月 16 16:34 xyz.java -rw-rw-r-- 1 soot soot 0 2月 16 15:26 xyz.txt [soot@soot-linux find_test]$ ~/scripts/findsh.sh . *.java final find + grep result: ← 期待とは違うように実行され、該当なし $1 = . $2 = abc.java ← ワイルドカード展開 $3 = xyz.java ← ワイルドカード展開 [soot@soot-linux find_test]$
マッチするファイルがないディレクトリで実行。→ うまくいく[soot@soot-linux find_test]$ cd .. [soot@soot-linux test]$ ls -l 合計 4 drwxrwxr-x 2 soot soot 4096 2月 16 16:34 find_test [soot@soot-linux test]$ ~/scripts/findsh.sh . '*.java' final find + grep result: ./find_test/abc.java:1:final ./find_test/xyz.java:2:final $1 = . $2 = *.java $3 = final [soot@soot-linux test]$