次のスクリプトは実行されませんが、構文エラーが発生するのはなぜですか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
ちょうど:
間に部分を置くそれからそしてその他発生した構文エラーを修正します。