bashのif文複数条件について

このQ&Aのポイント
  • bashのif文を使用して複数条件を書く方法についての質問です。
  • 具体的には、条件が複数あり、そのうちの一つがファイルの存在判定で、もう一つはファイル内の文字列の存在判定です。
  • しかし、条件を上記のように書いた場合にエラーが発生してしまい、解決方法を教えていただきたいです。
回答を見る
  • ベストアンサー

bashのif文複数条件について

お世話になります。 まず、下記のスクリプトをご確認ください。 if [ ! -f ${E_FILE} -o -f ${E_FILE} -a `grep -c 'ERROR' ${E_FILE}` -ne 0 ] ; then 上記条件文は次のような論理解釈で作成しました。 (${E_FILE}というファイルが存在しない) or  (${E_FILE}というファイルが存在する and ファイル内に'ERROR'という文字列が存在する) これを実行すると: too many argumentsというエラーが返ってきます。 原因をご存知の方がいればご教示いただきたく存じます。 よろしくお願いいたします。

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

  • ベストアンサー
  • entree
  • ベストアンサー率55% (405/735)
回答No.2

原因は${E_FILE}が存在しないからです。 まず、下記の部分についてどのように実行されるとお考えでしょうか? if [ ! -f ${E_FILE} -o -f ${E_FILE} -a `grep -c 'ERROR' ${E_FILE}` -ne 0 ] ; then おそらく、以下のように考えておられるのではないでしょうか? 1.test ! -f ${E_FILE} 2.これがFALSEなら test -f ${E_FILE} 3.これがTRUEならgrep -c 'ERROR' ${E_FILE} 4.test (3の結果) -ne 0 しかし、残念ながら実際には、 1.grep -c 'ERROR' ${E_FILE} →ファイルが存在しないのでエラー(標準出力はなし) 2.test ! -f ${E_FILE} -o -f ${E_FILE} -a -ne 0 2の部分で-a -ne 0の部分が文法エラーです。 理由は2が1つのコマンドとして解釈され、その前に``の部分が解釈されるからです。 されたいことを実現するには下記のように書くべきです。 if [ ! -f ${E_FILE} ] || [ -f ${E_FILE} -a `grep -c 'ERROR' ${E_FILE}` -ne 0 ]; then さらに言えば、[ ! -f ${E_FILE} ]がFALSEならtest -f ${E_FILE}は必ずTRUEなので、 下記のように簡略化できます。 if [ ! -f ${E_FILE} ] || [ `grep -c 'ERROR' ${E_FILE}` -ne 0 ]; then 余談ですが書かれているコードをきっちりと書くならこんな感じ。 if test ! -f "${E_FILE}" || grep 'ERROR' "${E_FILE}"` > /dev/null; then ・例えば上記のようなことがあるから、-a、-oはあまり使わないほうが良い (さらに、-a、-oは評価順序に関する規定が曖昧だから、右側から評価されても文句は言えない) ・変数はスペースが入ってきた場合を考慮してダブルクォーテーションで括る ・`grep -c ~` -ne 0はgrep ~ > /dev/nullで置き換えが可能 ・[]よりもtestを使う。(Autoconfのドキュメントにある移植性の高いプログラムを書くためのガイドライン)

anman0201
質問者

お礼

ご回答ありがとうございます。 頂いた方法で無事解決することができました。 またよろしくお願いいたします。

その他の回答 (1)

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

${E_FILE} というファイルが存在しないとき、 grep -c ERROR ${E_FILE} は、エラーメッセージを出して、標準出力への書き出しはありません。従って、 if [ ! -f ${E_FILE} -o -f ${E_FILE} -a -ne 0 ] となり、"[" コマンド の構文エラーになります。 そういうときは普通は、ファイルがあるときだけgrepを実行するようにします。 if [ ! -f ${E_FILE} ] || [ `grep -c ERROR ${E_FILE}` -ne 0 ] さらに普通には、 if [ ! -f ${E_FILE} ] || grep ERROR ${E_FILE} >/dev/null

関連するQ&A

  • Bシェルでのif文について

    あるファイルからgrepコマンドで抽出し、その値を変数に 入れてその値がNULLが確認したいのですが、うまくいきません。 どのようにすればNULLとして比較できますでしょうか。 ・「File」という名のファイル Period: Count: ※本来ならば「:」の後に数字が入るが 入っていない場合にはエラーとしたい ・grepの条件 TEST=`grep "^Period" File | cut -f 2 -d":"` ・if文 if [ ${TEST} != NULL ] then echo "ERROR" fi

  • シェルスクリプト(if文)

    bashにてシェルスクリプトを作成しています。 XXXX_111122222333_YYYYMMDD 111122222333 といった2パターンのファイル名から、「111122222333」の部分を取得したいのですが、if文の条件式で悩んでいます。 if [ expr length ${p9} -gt 13 ] then a=`echo $p9|cut -c 6-9` b=`echo $p9|cut -c 10-14` c=`echo $p9|cut -c 15-18` else a=`echo $p9|cut -c 1-4` b=`echo $p9|cut -c 5-9` c=`echo $p9|cut -c 10-13` fi これで実行すると too many arguments というエラーが出てしまいます。(結果も正しくありません) 基本的な部分が理解できていないかと思うのですが、宜しくお願いいたします。

  • シェルスクリプトのif文

    シェルスクリプトのif文について質問です。 あるファイルが存在しないときだけ処理を行いたい場合、 下記のような記述をするしかないのでしょうか? if [ -e /tmp/test.txt ]; then  ダミー処理(val1=1など意味のない処理)  (ダミー処理を入れるのは何も書かないとエラーとなってしまうため) else   行いたい処理 fi elseを使わずに if  fi だけですますことはできないでしょうか? -eはファイルが存在するならば真なので 逆に意味が真となるようにしたいのですが・・・

  • BシェルのIF文について。。

    BシェルのIF文について。。 現在、Bシェルで特定のファイルが存在する場合、ファイル名の末尾をカウントアップ(ファイル名_01)しようと考えております。 以下がスクリプトの内容なのですが fiが無効というエラーが出てしまいます。。。 対応が分かる方がいらっしゃれば教えてください。。 if [ -f aaa_00.txt] then touch aaa_001.txt fi よろしくお願いします。

  • if文について

    シェルについて殆ど無知なのでお聞きしたいのですが (質問内容自体シェルの内容に含まれないのかも知れませんが)、 if ( -e $xxx_DIR/$CHK_OK1 ) then rm $xxx_DIR/$CHK_OK1 と有った場合、$xxx_DIRで指定されたディレクトリに$CHK_OK1で指定されたファイル が有れば、そのファイルを消す。と言う解釈でOKでしょうか?

  • 複数存在するgrepについて

    自分はSolaris7(8)を使用しているのですが、grepが /bin/grep /usr/bin/grep /usr/xpg4/bin/grep の3つ存在しています。動作的には前者2つが同じようで、最後者がちょっと拡張されているように思われます。思うに大きな違いは"-f|-e"(ファイルにマッチすべき文字列を書いておくことが出来る)が大きいと思うのですが、そこで、 1) /xpg4 というdirectoryはどのような意味合いを持っているのでしょうか?どのような括りでこのディレクトリがあるのでしょうか? 2) 上に書いたオプションの違いのほかに、両者にはどのような違いが有るのでしょうか? 3) 通常、UNIXのユーザーは/usr/bin/grepがデフォルトで使っているというのが「正しい」と思うのですが、後者(xpg4)がデフォルトとして使われる場合にはどのようなケースがあるのでしょうか? --[参考]-- /usr/bin/grep [ -bchilnsvw ] limited-regular-expression [filename ... ] /usr/xpg4/bin/grep [-E | -F ] [-c | -l | -q ] [ -bhinsvwx ] -e pattern_list ... [ -f pattern_file ... ] [ file ... ] ---------- 宜しくお願いいたします。

  • シェルスクリプトでエラー値取得

    Linuxをつかいシェルスクリプトを組んでいます 複数ファイルの存在有無を確認し、問題なければ、 ファイルを作成する処理を作成したいと思っています。 現在つまずいているのが以下の2点です。  (1)複数ファイルが無い場合、エラーとしたいが、「too many arguments」とででしまう。  (2)HASH.tmp情報取得中にエラーとなったらエラーを出したいが、エラー終了ステータス返却処理に流れない。 初めてで色々しらべながらやっていますが、うまくいかず止まってしまいました。 どなたかご助言お願い致します。 (1) #==============================================================================# # データ抽出用sqlファイル存在確認 # CSVファイルが無かったらエラーを出したい。 # 終了ステータス返却 # 終了ステータスが"0"以外の場合は、"1"を返却する #==============================================================================# if [ ! -f "${DATA_DIR}/"*.csv ]; then # ログ出力 OUT_MSG_LOG -E "抽出ファイルが存在しません。" OUT_MSG_LOG -E "抽出シェル - 終了 終了ステータス :1" OUT_ACT_LOG SH 12 "" OUT_ACT_LOG SH 02 "" exit 1 fi (2) #==============================================================================# # ハッシュ情報取得処理 #==============================================================================# mktemp ${DATA_DIR}/HASH.tmp >/dev/null for arg in *.csv do md5sum ${arg} | awk '{printf("%s,%s\n",$2,$1)}' >> HASH.tmp done #==============================================================================# # 終了ステータス取得 #==============================================================================# RS=$? #==============================================================================# # エラー終了ステータス返却 # 終了ステータスが"0"以外の場合は、"1"を返却する #==============================================================================# if [ ${RS} -ne 0 ]; then # ログ出力 OUT_MSG_LOG -E "抽出処理実行中にエラーが発生しました。" OUT_MSG_LOG -E "抽出シェル - 終了 終了ステータス :${RS}" OUT_ACT_LOG SH 12 "" OUT_ACT_LOG SH 02 "" exit 1 fi

  • シェルスクリプトにおけるreadコマンドについて

    シェルから読み込まれる"param_file"において、 A B といった途中に空白を含む行が存在する場合、 while read PARAM if [ $1 = ${PARAM} ] then break fi done < "param_file" を実行すると if文実行時に "too many arguments"エラーが発生します。 Solalis上で同じ処理を実行してもエラーが 発生ませんが、Linux特有なのでしょうか。

  • シェルスクリプト文字列の処理について

    はじめましてよろしくお願いします。 質問サイトもシェルも初心者なので至らない点がございましたら ご容赦の程よろしくお願いします。 下記シェルスクリプトを実行すると下記エラーが発生します。 「test2」変数に空白無しで「abc」と入力するとエラーは発生しません。 変数test2の値(a bc)を変更せずにエラーが発生しない方法はないでしょうか? 手段でもかまいませんので教えてください。 ========================= testsh110207.sh ====================================== #!/bin/sh test1="abc" test2="a bc" if [ ${test1} = ${test2} ] then echo "=:文字列1と文字列2が等しい場合に真" echo "test1の「${test1}」と、test2の「${test2}」は等しい" fi if [ ${test1} != ${test2} ] then echo "!=:数値1と数値2が等しくない場合に真" echo "test1の「${test1}」と、test2の「${test2}」は等しくない" fi echo "********* テスト完了 *********" ======================================================================= $ ./testsh110207.sh ./testsh110207.sh: line 6: [: too many arguments ./testsh110207.sh: line 13: [: too many arguments ********* テスト完了 *********

  • firefoxでfunction(e){}の e を省略するには?

    <html> <body> <input type="text" onkeydown="test()"> <script> function test(){ var e=getEvent()||window.event; o=e.target||e.srcElement; o.style.backgroundColor='#f00'; alert(e.keyCode); } function getEvent(){ var ob, c = arguments.callee; while(c = c.caller) if(ob = c.arguments[0]) return ob; } なんとなく取得できているようなのですが、 バグがありそうで、ご意見を! </script> </body></html>