• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:シェルスクリプト bashのtestコマンドが動きません)

シェルスクリプトのtestコマンドが動かない理由と解決法

このQ&Aのポイント
  • シェルスクリプトの移行に伴い、SUN-solaris8からLinuxE3.0に移動した際にtestコマンドがエラーになりました。
  • 具体的には、test -s ../directory名/file名で指定した場合にLinuxではエラーメッセージが表示されて終了してしまいます。
  • 解決法としては、マニュアルを参照し、testコマンドの引数を[]で囲むように書き換えることで正常に動作するようになります。

質問者が選んだベストアンサー

  • ベストアンサー
  • notnot
  • ベストアンサー率47% (4900/10359)
回答No.2

SUNであろうがLinuxであろうが、test -s の後に書けるファイル名は1つだけです。SUNで、test -s *.log が動いていたのはたまたまマッチするファイルが0または1つだけだったのでしょう。 >if test -s XXXX.log || YYYY.log これは、間違いです。これは、 XXXX.logが存在してファイルサイズが0でなければ、この後のthen部分を実行する。XXXが存在しないか、ファイルサイズが0なら、「 YYYY.log というコマンド」を実行するその結果が真ならその後のthen部分を実行する。 という意味不明の記述です。 何をしたいのか説明文(?)から読み取れないのですが、*.log というファイルが1つ以上あり、それらすべてサイズが0でないということを調べたいのでしょうか? FLAG=true for i in *.log do if test -s $i; then :; else FLAG=false; fi done if $FLAG then echo "すべての *.log ファイルのサイズが非ゼロ" else echo "*.logが存在しないか、少なくとも一つの *.log ファイルのサイズがゼロ" fi

masato0703
質問者

補足

ご回答ありがとうございます。 testコマンドは*は使用不可能だったことが分かり助かりました。 実行したいことは if test -s (XXXX.log || YYYY.log ||・・・・) と書くのでしょうか。 コーディングの仕様は あるプログラムを動かしたとき 正常動作ならば ifの条件( *.log というファイルが1つ以上あり、 それらすべてサイズが0でないなら) thenの実行 elseの条件( 動かしたプログラムが異常なら途中でストップし、*.log が1つも 存在しない) だから elseでexitさせたい という希望です。 *.logが出れば必ずサイズがあるのは前提です。 ひょっとして想定外の不具合で*.logが出てもファイル サイズが0はありうるかもしれませんが、今回は 考慮に入れてませんでした。 お書きになったfor 文は解決のヒントになりました。 testコマンドでは*は無理ということも勉強になりました。 Linuxがはきだしたコメント見ればわかったはず。 反省してます。 やはり第3者に作ったプログラムを読んでいただくことは 技術の向上に欠かせないです。でもうちの環境では 出来る人はいるのですが、給料成果主義のせいか いつ尋ねても、忙しいから自分でやれで終わります。 自分で本を購入したり、HPで検索しながら 使えそうなコマンドを探して書いている状況です。 分かりにくい文章を丁寧に判読してくださりありがとうございます。 こちらの検討した仕様に考慮不足や補足情報が必要でしたら ご指摘ください。

その他の回答 (3)

  • notnot
  • ベストアンサー率47% (4900/10359)
回答No.4

>FLAG=true   ←FALG変数にtrueを設定 >for i in *.log  ←全logファイルチェックのfor文 >do >if test -s $i   ←1つ目のlogの存在確認 1つ目とは限りませんけどね。 >then :; ←:は何の役目ですか? 1つ目のlogが存在すれば何もしない : は何もしないコマンドです。条件を逆にして、 if test ! -s $i ; then FLAG=false; fi でもいいんですが。 >else FLAG=false;  ←1つ目のlogの存在したのでFLAG変数にfalseが設定 -s $i が偽のときつまり、ファイルが存在しないかサイズが0のとき設定 >fi >done ←logがなくなるまでforを繰り返す > >if $FLAG  ←$FLAGって何をしめしますか? $FLAG は、true か false かどちらかです。 一回もforループ内のelseに来ないとき、つまりすべての*.logファイルのサイズが非0のときにFLAGはtrueのままです。一度でもelseに来ていればつまりどれかひとつでもファイルサイズが0ならfalse。 *.logという名前にマッチするファイルがひとつもなければ、forループはiの値が"*.log"という文字列のままで一度だけ実行され、そういう名前のファイルはないので、test -s $i は偽になって FLAG=false になります。 $FLAGがtureかfalseかによって、最後のif文のthen部かelse部かのどちらかが実行されるわけです。

masato0703
質問者

お礼

こんばんは 本当に助かりました。 FOR文を使うのは気が付かなかったです。 ちゃんと動きました。 一つ疑問があって シェル実行中に 下のメッセージが出るのですが include .cshrc_Lx これは何か設定がまずいのですか?

masato0703
質問者

補足

ご回答ありがとうございます。 >$FLAGがtureかfalseかによって、最後のif文のthen部かelse部かのどちらかが実行されるわけです。 IF$FLAGってくっつけてもOKですか?IFと$間に空間がいるとか。 trueの場合最後のif文のthen部かelse部はthenの部分で、 falseのときはelseが実行されるんですね。 月曜日に会社へ行ってやってみます。 成功したら、とっても嬉しいです。 月曜の晩までお礼お待ちくださいませ。

  • notnot
  • ベストアンサー率47% (4900/10359)
回答No.3

test で複数ファイルを調べるなら、 test -s XXX.log -a -s YYY.log -a -s ZZZ.log と、-a でつなぎます。and の意味です。or は -o 。 X || Y というのは、コマンド A を実行してエラーのときに B を実行するという意味です。 私の書いたのでご希望の仕様になっていると思いますが、for 文を使っちゃだめなんですか?(ファイルが存在しないかサイズゼロのときFLAGがfalseになって次のifでそれを調べる)

masato0703
質問者

補足

ご回答ありがとうございます。 FOR文でもなんでも使ってよいです。 提案してくださったスクリプトを 自分なりに解読してみました。 FLAG=true   ←FALG変数にtrueを設定 for i in *.log  ←全logファイルチェックのfor文 do if test -s $i;   ←1つ目のlogの存在確認 then :; ←:は何の役目ですか? 1つ目のlogが存在すれば何もしない else FLAG=false;  ←1つ目のlogの存在したのでFLAG変数にfalseが           設定 fi done ←logがなくなるまでforを繰り返す if $FLAG  ←$FLAGって何をしめしますか? then echo "すべての *.log ファイルのサイズが非ゼロ" else echo "*.logが存在しないか、少なくとも一つの *.log ファイルのサイズがゼロ" fi if $FLAGこのIF文のは$FLAGは何を判定してますか?

  • notnot
  • ベストアンサー率47% (4900/10359)
回答No.1

具体的にどのようなディレクトリ構成で、具体的にどのようなコードを書いて、具体的にどのようなエラーメッセージが出たんでしょう? >Linuxで >% sh と打つと/bin/bash >% test と打つと /XXX/usr/binだったかな?パス忘れました。 この文章も意味不明です。説明力が無いのなら、そのままコピーペーストしてください。

masato0703
質問者

補足

毎度ご迷惑おかけします。 SUNからLinuxへシェルを移植して急に動かなかったので 気が動転してました。 スクリプトは簡略化させていただきました。 やりたいこと あるプログラムを実行したあと、 スクリプトでlogファイルの存在(1個以上かつ名前も複数) を調べるのにXXXX.logやYYYY.logに正常終了ならXXXX.logやYYYY.log ファイルの最終行にFINISHが出る仕様なのでgrepで拾う。 異常終了はxxx.logファイル自体が出ない その時点でエラーストップさせたい。 別の場所にERRORのログファイルが出る if test -s *.log then grep FINISH *.log > FINISH_log else echo ' [ERROR]' exit fi このスクリプトを実行したら test: too many arguments とメッセージでた。複数ファイルはいけませんという意味らしい。 grep FINISH *.log > FINISH_log は上手く手来ました。 Linuxで、testコマンドは*(ワイルドカード)指定で 複数ファイルの参照は仕様上無理ですか? なにか上手い解決方法があれば、ご教示お願いします。 if test -s XXXX.log || YYYY.log は認識できました。 echo $status は 0 ゼロリターンでした。 このXXXX.logファイルはいろんな名前(ただし.logは共通) で100個程度出てきます。やはり全てのファイル名 をダブルパイプで連結しかありませんか?

関連するQ&A

専門家に質問してみよう