シェルスクリプトのエラーに対する解決方法

このQ&Aのポイント
  • 質問者は特定のフォルダ内に2つの圧縮ファイルが存在する場合、bbb.log.1を削除し、存在しない場合はメッセージを表示するシェルスクリプトを作成しました。
  • しかし、実行すると「./test.sh: line 15: [: -e: binary operator expected」というエラーが表示されます。
  • 正しく動作させるためには、if文の条件式を正しく記述する必要があります。
回答を見る
  • ベストアンサー

ある特定のフォルダの中に、2つの圧縮ファイルが存在すれば、bbb.lo

ある特定のフォルダの中に、2つの圧縮ファイルが存在すれば、bbb.log.1を削除し、存在しなければその旨をmessagesに記述するというシェルスクリプトを作成しました。 (OSはCentOS5.4で、cronで作成したシェルスクリプトを動作させております) <シェルスクリプトの内容> #!/bin/sh DATE=`date +%Y%m%d --date '1 day ago'` i=/var/log/aaa/bbb.log j=/var/log/aaa/ccc.log cat $i.1 | grep type=ccc > $j.$DATE sed '/type=ccc/d' $i.1 > $i.100 /bin/mv $i.100 $i.$DATE /bin/gzip $i.$DATE /bin/gzip $j.$DATE if [ test -e $i.$DATE.gz ]; then if [ test -e $j.$DATE.gz ]; then rm -f $i.1 else logger -p user.info "not find ccc.log" fi else logger -p user.info "not find bbb.log" fi これを実際に動作させますと、以下のエラーが表示されます。 ./test.sh: line 15: [: -e: binary operator expected どのように記述すれば正しく動作するのでしょうか。 お手数をおかけしますが、よろしくお願い致します。

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

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

if 文(やwhile文等)では、その後にくる「コマンド」の実行後のステータスで分岐します。 if grep 'a' foo.txt ; # foo.txtのaという文字が含まれているならば この使い方で、便利なコマンドとしてtestがあります。testは数値比較や文字列の比較、and/or等の論理演算を行って、その真偽をステータスとして返します。 このtestコマンドの「別名」が [ です。 [と]でくくることで、多言語のif文で条件を () でくくったような見た目になります。 そこで、エラー箇所を見ると > if [ test -e $i.$DATE.gz ]; then と、 [ と testの両方が指定されています。これでは、 [ コマンドの引数として test が指定してあることになります。 -e は単項演算子なので、 'test' -e ~ という式がおかしい( 「値」のあとには二項演算子が必要なのに単項演算子がきている )というエラーになっているのです。 if [ -e $i.$DATE.gz ]; then # [ を使う か if test -e $i.$DATE.gz ; then #testを使う としましょう。 あと、これをcronで実行させる、とのことですが、cronは環境変数の設定を行いません。 よって、PATHは設定されません。 そのため、 grep,sed,date等のコマンドは見付けることができず実行できません。 スクリプト中でPATHを指定するか、コマンドをフルパスで書くか、してください。

murakenjapan
質問者

お礼

とても分かりやすい回答、ありがとうございました。 tux_the_penguinさんからもご指摘を受けましたとおり、自分はこれを→[] testというコマンドの記述方法の一部だと勝手に解釈しておりました。 ありがとうございました。m(__)m

その他の回答 (2)

回答No.2

#1の方もおっしゃっていますが [ ← この文字は見やすくするための記号ではなく test と言うコマンドの別表記なんですよ

murakenjapan
質問者

お礼

ご回答ありがとうございます。 ご指摘のとおりで、自分は[]はtestコマンドの一部と勝手に解釈しておりました。 とても勉強になりました。

  • vaguechat
  • ベストアンサー率85% (47/55)
回答No.1

二つのif文について if test -e $i.$DATE.gz; then か if [ -e $i.$DATE.gz ]; then かのどちらかにするとどう?

murakenjapan
質問者

お礼

ご回答ありがとうございます。 ご指摘のとおり、どちらかの記述に変更致します。 ありがとうございました。

関連するQ&A

  • Linuxを勉強中のものです。

    Linuxを勉強中のものです。 IF文の複合文で困っております。 (OSはCentOS5.4です) #!/bin/sh DATE=`date +%Y%m%d --date '1 day ago'` address1=test@test.co.jp address2=admin@test.co.jp subject1="ccc.logは削除されませんでした" subject2="ccc.logは削除されました" subject1=`echo $subject | nkf -j` subject2=`echo $subject | nkf -j` honbun1="bbb.logが見付からなかったため、ccc.logは削除されませんでした。" honbun2="aaa.logが見付からなかったため、ccc.logは削除されませんでした。" honbun3="ccc.logは削除されました。" if [ -e aaa.gz ]; then if [ -e bbb.gz ]; then { rm -f ccc.log; mail -s "$subject2" $address1 -- -f $address2 << honbun; `echo $honbun3 | nkf -j`; honbun; } else { mail -s "$subject1" $address1 -- -f $address2 << honbun; `echo $honbun1 | nkf -j`; honbun; } fi else { mail -s "$subject1" $address1 -- -f $address2 << honbun; `echo $honbun2 | nkf -j`; honbun; } fi 上のシェルスクリプトを実行すると、エラー表示され動作しません。 エラー >> line 32: syntax error: unexpected end of file どんな些細な情報でも結構ですので、ご教授下さい。 宜しくお願い致します。

  • gzipで圧縮されたファイルを伸張して保存

    gzipで圧縮されたファイル(sample.txt.gz)を伸張して「sample.txt」として保存し直したいのですが、スクリプト内でどういうふうに書けばいいのかわかりません。 gzipのパスは、#!/bin/gzip gunzip sample.txt.gz や gzip -d sample.txt.gz のコマンドを使うらしいことはわかったのですが、これをどうスクリプト中に書けばいいのか。。。 どなたかわかる方、教えてください。

    • ベストアンサー
    • Perl
  • tar圧縮ファイルが作成できず困っています。

    tarとgzipをパイプでつなげて使用すると、tar圧縮ファイルが正常に 作成できず困っています。(Solaris) *やりたいこと* ファイル一覧test.txtに記載されているファイルを一度に tar圧縮したい。(tar・gzip別々でなく) *コマンドライン* # tar cvfp - -I test.txt | gzip -c > test.tar.gz a aaa.txt 1K a bbb.txt 1K a ccc.txt 1K # ls -l test.tar.gz(←とりあえずファイルは作られている) -rw-r--r-- 1 root other 33235 5月 12日 10:03 test.tar.gz # gunzip test.tar.gz(←unzipもできる) gunzip: /usr/bin/gzip has 2 other links -- unchanged # ls -l test.tar -rw-r--r-- 1 root other 64076 5月 12日 10:03 test.tar # file test.tar(←この時点でおかしい。file種別がアーカイブじゃない) test.tar: ELF 32-ビット MSB 実行可能 SPARC バージョン 1[動的にリンクされています][取り除かれています] # tar xvfp test.tar(←エラーになる) tar: ディレクトリの検査合計エラーです。 # /bin/tar xvfp test.tar(←違うtarでやってみるとエラーがでる) tar: This does not look like a tar archive tar: Skipping to next header tar: Archive contains obsolescent base-64 headers tar: Read 2636 bytes from test.tar tar: Error exit delayed from previous errors 上記のような現象になって困っています。パイプ以降をcompressに するとふつうにいけるので、gzipがおかしいような気もするのですが。 サイトを検索するとみなさんGNUのgtarをお勧めしているようですが そちらもだめでした。 どなたか解決策をご存知の方がいたらご教授願います。

  • バックグランド実行+ログアウトでジョブが残るのは?

    以下のようなシェルをバックグランド実行した後、ログアウトしてもジョブ(プロセス)が残っているのはなぜなのでしょうか? バックグランド実行しても、ログアウトするとバックグランドプロセスはkillされてしまう。だからnohupを使いましょう、、とネットではよく書かれています。自分でこれを検証試みた結果、想定の 動きとならなかったので質問させてもらいました。 以下シェルを 「 ./test01.sh & 」と実行させるのですが、別コンソールでプロセスを監視している限り、最後まで動作し続けるのです。 どなたかおわかりになる方教えてください。 ◇検証用シェル #!/bin/sh echo "start" > ./test01.log for ((i=0 ; i<3 ; i++)); do sleep 60 echo $i >> ./test01.log date >> ./test01.log done

  • 2時間おきに時刻を新規ログに書き込む

    Linuxで2時間おきに時刻を新規のログに書き込みたいのですが、 うまく表示されません。 syslog.confに新しく2時間おきに時刻を書き込むログを加え、 新規ログに Sep 18 07:00:01 tky015 logger: 只今の時刻は 7時00分です Sep 18 08:00:01 tky015 logger: 只今の時刻は 8時00分です Sep 18 09:00:01 tky015 logger: 只今の時刻は 9時00分です Sep 18 10:00:01 tky015 logger: 只今の時刻は 10時00分です Sep 18 11:00:01 tky015 logger: 只今の時刻は 11時00分です という風に表示させたいです。 新規ログをtest.logとし、メッセージの表示はシェルを使用し、以下のようになりました。 ファイル名はtime.shです。 #!/bin/sh MESS='只今の時刻は' DATE1=`date "+%k"`'時' DATE2=`date "+%M"`'分' MESS=$MESS$DATE1$DATE2'です' logger -f /var/log/test.log $MESS 2時間おきに時刻を表示させるためにcronを使い、 * */2 * * * /bin/sh /root/time.sh syslog.confには、 #2時間おきに時間を書き込むログ cron.*         /var/log/test.log というふうにやりましたが、 時刻は/var/log/messagesに書き込まれてしまい、/var/log/test.logには Sep 17 07:00:01 tky015 crond[6480]: (root) CMD (/bin/sh /root/tanaka.sh) Sep 17 08:00:01 tky015 crond[6486]: (root) CMD (/bin/sh /root/tanaka.sh) Sep 17 09:00:02 tky015 crond[6492]: (root) CMD (/bin/sh /root/tanaka.sh) Sep 17 10:00:01 tky015 crond[6499]: (root) CMD (/bin/sh /root/tanaka.sh) Sep 17 11:00:01 tky015 crond[6506]: (root) CMD (/bin/sh /root/tanaka.sh) というふうに書かれてしまいます…。 syslog.confの書き方が間違っているんじゃないのかなと思うのですが、 どうすればいいのかわかりません。 OSはCentOS05です。 初心者ですので分からないこともあるかも知れませんが、 どなたかご教授ください。 よろしくお願いします。

  • シェルスクリプトのコマンド グループ化における変数の有効範囲について教

    シェルスクリプトのコマンド グループ化における変数の有効範囲について教えてください。 中括弧"{ }"を使うと親プロセス(=その実行中のプロセス)にて実行、 小括弧"( )"を使うとサブシェル(=子プロセス)にて実行されると認識しています。 また環境変数は子プロセスに引き継がれ、シェル変数は引き継がれないと認識しています。 以下のシェルスクリプト(Bシェル)でテストしたところ、続くような結果となりました。 ~スクリプト内容~ #!/bin/sh ##TEST1 VAR01=AAA { echo 中括弧内でVAR01は${VAR01}; } ( echo 小括弧内でVAR01は${VAR01}; ) ##TEST2 { VAR02=BBB; echo 中括弧内でVAR02は${VAR02}; } echo 外でVAR02は${VAR02} ##TEST3 ( VAR03=CCC; echo 小括弧内でVAR03は${VAR03}; ) echo 外でVAR03は${VAR03} ~実行結果~ 中括弧内でVAR01はAAA 小括弧内でVAR01はAAA 中括弧内でVAR02はBBB 外でVAR02はBBB 小括弧内でVAR03はCCC 外でVAR03は  VAR02、VAR03の結果は納得できます。 またVAR01が{ }に引き継がれているのも納得できました。 しかし、VAR01はシェル変数として作成した(exportによる環境変数化はしていない)にも関わらず、子プロセスである( )内処理にも引き継がれているのはなぜなのでしょうか? 

  • シェルスクリプトについて

    シェルスクリプトについて Linuxで先頭にスペースが入っている行をひとつ上の行につなげたいと考えています。 その場合、シェルスクリプトはどのように書けばよいかご教示願います。 【ファイル内容】 aaa △bbb ccc ddd (b行の先頭のみスペース(△)が入っています。) 【変換後のファイル】 aaa bbb ccc ddd

  • ファイルから文字列を読み込むシェルスクリプトの作成

    現在シェルスクリプトの勉強をしています。 ファイルから文字列を読み込み表示するだけのシェルスクリプトを 作成しているのですが、エラーが出てうまくいきません。 ./test.sh: line 10: syntax error near unexpected token `done' 以下の通りファイルを作っています。 改行コードはLF、文字コードはSJISとなっています。 どのあたりが間違っているのか教えて頂けますでしょうか。 よろしくお願いします。 test.sh --------------------- #!/bin/sh LIST=./abc.lst while read F1 echo ${F2} break done < ${LIST} } --------------------- abc.lst --------------------- AAA BBB CCC ---------------------

  • Windowsで言う『ctrl+A→ctrl+C→違うファイルを開いてCtrl+A→Ctrl+V』

    Windowsで言う『ctrl+A→ctrl+C→違うファイルを開いてCtrl+A→Ctrl+V』と同じ動きをするスクリプトを作っています。 ctrl+A,ctrl+Cするファイルはxxx.gzです。 ctrl+A,ctrl+Vするファイルは./aaa/bbb.cccです。 <?php $lines = gzfile("xxx.gz"); $lastfile = fopen("./aaa/bbb.ccc", "rwb+"); foreach($lines as $line){ $txt .= $line; } $lastview = fwrite($lastfile,$txt); fclose($lastfile); ?> 上記の方法だと、bbb.cccファイルの内容が "あいうえおかき"で、xxx.gzファイルが "かきくけこ"の時、 スクリプト後に bbb.cccファイルは"かきくけこかき"になってしまいます。 希望は、スクリプト後のbbb.cccファイルの内容が "かきくけこ"にしたいのです。 この方法がわかりませんので教えてください。

    • ベストアンサー
    • PHP
  • 解凍した内容を別のファイル名で保存

    圧縮ファイル($filename.gz)を解凍し、 解凍した内容を別のファイルに書き込み保存するスクリプトを考えています。圧縮されているファイルは解凍するとxmlファイルですが、下記のスクリプトの方法ですと解凍されず、対象のxmlファイルは0バイトです。 「概念から間違っているのかなぁ」と考えもしましたが、 ちゃんと解凍して./aaa/bbb.xmlファイルに書き込む方法がわからず質問させていただきました。 どうかご教授願います。 ※$filename.gzというのはこのスクリプトの直前で作られている圧縮ファイルです。このファイルのファイル名・内容については問題ないことを確認しています。 ============ <?php ~ touch("./aaa/bbb.xml"); $decompress = "/usr/bin/gzip -dc $filename.gz"; $result = system(escapeshellcmd($decompress)); $lastfile = fopen("./aaa/bbb.xml", "rwb+"); $lastview = fwrite($lastfile, $result); fclose($lastfile); ~ ?> ============

    • ベストアンサー
    • PHP