• 締切済み

testコマンドifコマンドについて

testコマンドifコマンドについて fedoracore9で現状のフォルダ構成が以下になります。 /a/aa/filename /a/ab/ /a/ac/filename /a/ad/ ・ ・ ・ filenameというファイルがある場合はコマンド1をない場合はコマンド2を実行するシェルを書いてみました。 fname=filename if test -f /a/*/$fname then コマンド1 else コマンド2 fi 以上を作成しましたがうまくいきませんでした。各フォルダともコマンド1しか実行されませんでした。 2階層目の各フォルダに対してif文を実行する場合はどのようにすればよろしいのでしょうか。 よろしくお願いいたします。

みんなの回答

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

「*等の展開はシェルが実行して、それがコマンドに渡される」 シェルの動作の基本ですので、覚えておきましょう。 > test -f /a/*/$fname まず、シェルが変数や * によるファイル名の展開を行います。 この時点で、該当する ファイル名がなければ、展開されません。 シェルの設定により、そのまま /a/*/filename になるか($fnameの展開は可能なので) 、no match 等とエラーとなりスクリプトが停止するか、です。 コマンド2が実行されない、ということからすると、後者のエラーで停止、になっていると思われます。 該当するファイルが1つなら、 /a/*/$fname が展開されても一つだけになるのですが、複数ある場合はその全てが列挙されます。質問文にある例なら /a/*/$fname → /a/aa/filename /a/ac/filename となります。 testコマンドが受けとるのは、上記の展開が済んだ後のものです。 testコマンド自体が * を解釈して、該当するファイルが存在するかどうか探すわけではありません。 ファイルが1個なら、成功します。これは「パターンにマッチしたファイルがあるから」ではなく「指定したファイルが存在するから」です。たとえば、 /a/aa/filename しかなかった場合は test -f /a/aa/filename を実行しただけです。 該当ファイルが複数あると、例えば test -f /a/aa/filename /a/ac/filename となり、演算子が足りないのでtestがエラー → elseを実行となるはずです。 存在しない、かつ、エラーになる設定になっていない場合、 test -f '/a/*/filename' が実行され、存在しないので失敗 → else節となります。 これも、testが *をパターンとして処理したわけではなく「*」というディレクトリ名だと解釈したものです。 なので、展開しないように test -f '/a/*/filename' とすれば、コマンド1を実行していたケースでもコマンド2が実行されるようになります。 filenameが複数あるとき、一つ一つにコマンド1を実行したいのか 複数あってもコマンド1は1回だけ実行したいのか、によって最適な方法が違うでしょうが、 別のやりかたを考えた方がいいです。 例えば test `find /a/* -name "$fname" -depth 1 | wc -l` -ne 0 # findで該当ファイルを検索→wcで数を数えて、それが0でなければ など

  • hsmt_a
  • ベストアンサー率0% (0/2)
回答No.2

こんにちは。 書き方は間違っていないと思いますが、一点。 testコマンドの-fオプションは、そのファイルのタイプがファイルであるか、をチェックします。 よって、 $fnameがファイルであればコマンド1を実行します。 $fnameがディレクトリであった場合、コマンド2を実行します。 という動きになっています。 下記のように、ファイルが存在するか、をチェックする -eのオプションを使われてみてはどうでしょうか。 今:if test -f /a/*/$fname 改:if test -e /a/*/$fname

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.1

>fedoracore9で 正確にはFedora 9かと。(Coreは付かない) なにゆえそんな古いものを使用されているのか…は置いておいて……。 >fname=filename >if test -f /a/*/$fname だと、シェルによって if test -f /a/aa/filename /a/ab/filename /a/ac/filename /a/ad/filename … と展開されるかと思われますが………。 for文などで処理するようにした方がよいのではないですかね? fname=filename for fname2 in /a/*/$fname do  if test -f $fname2 ; then   コマンド1  else   コマンド2  fi done でしょうかね?

head500
質問者

補足

早速のご回答ありがとうございます。 >if test -f /a/aa/filename /a/ab/filename /a/ac/filename /a/ad/filename … >と展開されるかと思われますが………。 その通りです。そこで教えていただいたことをやってみたのですが、どうもfor fname2 in /a/*/$fnameの*の指定方法で/a/aa/filenameが存在した時点で他のフォルダである/a/ab/ /a/ad/にもコマンド1が実行されているようです。 やりたいこととしては、各々のフォルダで第二階層内のfilenameを見て条件分岐をさせたいとおもうのですが。。。 ちなみに *のところにabやadをいれるとうまくいきます。 なにかいい方法はありますでしょうか。。。

関連するQ&A