ファイル判定で以下のように書くと
「unexpected operator」とエラーになります。
if [ -f /path/*.txt ]; then
echo "OK"
fi
以下のように書けばエラーにならない
if [ -f /path/hoge.txt ]; then
echo "OK"
fi
ワイルドカードを使って1つもファイルがないか、あるいは1つでもファイルがあるかを判定したいのですが、
どう書いたら良いでしょうか。
ワイルドカードが先に展開されて test コマンド(if [ ~ の "[" の実体)の引数になってしまうので、期待した動作にならないはずです。
sh -x スクリプトファイル名
とすれば、その様子が分かると思います。
で、単純に ls コマンドの戻り値を使う方法が考えられます。
ls /path/*.txt >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "No match" else echo "At least one file" fi
ワイルドカードが先に展開されて test コマンド(if [ ~ の "[" の実体)の引数になってしまうので、期待した動作にならないはずです。
sh -x スクリプトファイル名
とすれば、その様子が分かると思います。
で、単純に ls コマンドの戻り値を使う方法が考えられます。
ls /path/*.txt >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "No match" else echo "At least one file" fi
コマンドの戻り値を使う場合には、普通、こう書きます。
if ls path/*.log > /dev/null 2>&1 then echo "OK" else echo "NG" fi
# 説明のために、敢えて冗長に書いたのであれば失礼をご勘弁
おお、スマートな方法ですね。参考になります
ファイルとディレクトリを判定したいとか、読み込み可能か、など test コマンドのパラメータをフルに使いたければ、シェルの関数を書いてあげる感じになります。
# 引数で指定されたファイルがあるかどうかを確認する関数 is_file_exist() { for f in $* do if [ -f $f ] then return 0 fi done return 1 } # こうやって使います if is_file_exist path/*.txt then echo "OK : txt" else echo "NG : txt" fi
# 使う方で [ や ] がないのは、間違いじゃないですよ :-)
ループで取ればいいんですね。なるほど
ワイルドカードは、該当ファイルが存在すれば元の文字列が変化しますが、存在しなければ元の文字列そのままになるので、AWKを使って文字列が変化した(=該当ファイルがあった)ら"OK"を表示する、というスクリプトを書いてみました。
echo /path/*.txt | awk '$0!="/path/*.txt"{print "OK";}'
ちなみに、AWKの動作をprintではなくてexitにすれば後のシェルスクリプトで分岐させることもできます。
(a)case文で
echo /path/*.txt | awk '{exit ($0!="/path/*.txt")?0:1;}' case $? in 0) echo "OK";; *) echo "NG";; esac
(b)if文で
echo /path/*.txt | awk '{exit ($0!="/path/*.txt")?0:1;}' if [ $? -eq 0 ]; then echo "OK" else echo "NG" fi
いろんな書き方がありますね。
ありがとうございます。
コマンドの戻り値を使う場合には、普通、こう書きます。
# 説明のために、敢えて冗長に書いたのであれば失礼をご勘弁
2015/05/13 19:18:18おお、スマートな方法ですね。参考になります
2015/05/14 10:40:42