"else"が空の "then"句の後に来ると、Bash構文エラーが発生します。

"else"が空の "then"句の後に来ると、Bash構文エラーが発生します。

次のスクリプトは実行されませんが、構文エラーが発生するのはなぜですかelse

LOGS3_DIR=~/logs
if [ -d "$LOGS3_DIR" ]; then
 cd
 cd "$LOGS3_DIR"
 echo "$LOGS3_DIR"
 for filename in `find "." -mtime 1 -type f`
  do
  if lsof "$filename" > /dev/null
  then
    # file is open
  else
    echo "deleting $filename"
    rm "$filename"
  fi
 done
fi

答え1

一つ作ってみたいと思いますねアクションなしファイルがすでに開いている場合は、空の:コマンドを1つ追加する必要がありますbash

if lsof "$filename" > /dev/null; then
  # file is open
  :
else
  printf 'deleting %s\n' "$filename"
  rm -- "$filename"
fi

これを使用しないと、:コードbashは解析されず、このようなエラーが表示されますbash: syntax error near unexpected token 'else'

答え2

別のオプションは、ロジックを反転することです。

if ! lsof "$filename" >/dev/null;then
    echo "deleting $filename"
    rm "$filename"
fi

答え3

出力にコマンド置換を使用しないでくださいfind。ここでは、次の操作ですべての操作を実行できますfind

find . -mtime 1 -type f ! -exec lsof -t {} \; -exec rm -f {} \; > /dev/null

いくつかのfind実装(findソースFreeBSDとGNUを含むfind)では。-delete-exec rm...

thenエラーが発生するのは、および間にコマンドがなく、一部のelseシェル(この構文のソースであるBourneシェルで始まる)に少なくとも1つのコマンドが必要なためです(そしてコメントはコマンドではありません)。これは完全にランダムであり、これらのシェルではこれを行う理由はありません。yashそして、zshこれらの制限はありません(if false; then else echo x; fiそれでもうまくif false; then else fiいきます)。

他の人が言ったように、:(or for nothing in; do nothing; done)のようなnoopコマンドを使用する!か、キーワードを使用してロジックを反転することができます(POSIXシェルでは使用可能ですがBourneシェルでは使用できません(そのシェルではforを使用するのが一般的です:)) 。mkshそしてyashそれはサポートされていますif false; then () else echo x; fi(将来のバージョンで変更される可能性があるため、これに依存しません)。

別の方法は次のとおりです。

lsof... || {
  cmd1
  cmd2
}

違いの1つは完全な終了状態、つまり失敗lsof時の終了状態ですlsof

答え4

長い話を短く

他の答えのうち、実際に元の質問を解決することはありません。コマンドで構文エラーが発生するのはなぜですか?これは間にコマンドがありません。それからそしてその他

不足しているコマンド

元のコードは次のとおりです。

if lsof "$filename" > /dev/null
then
  # file is open
else
  echo "deleting $filename"
  rm "$filename"
fi

問題はあなたの間にコメントがあるということですそれからそしてその他しかし、コメントはコマンドとは見なされません。つまり、問題を構造的に次のように書き直すことができます。

$ if true; then else echo; fi
bash: syntax error near unexpected token `else'

Bourne 組み込みによる構文の変更

実際のコマンドを前に置くことでこの問題を解決できます。その他しかし、コメント自体は機能しません。これもしそうならセクションは空白にできません。プレースホルダーが必要な場合は使用できます。内蔵コロン。たとえば、

$ if true; then :; else echo; fi

ちょうど:間に部分を置くそれからそしてその他発生した構文エラーを修正します。

関連情報