回答:
の出力でコマンド置換を使用しないでくださいfind
。ここでは、すべてを次のように実行できますfind
。
find . -mtime 1 -type f ! -exec lsof -t {} \; -exec rm -f {} \; > /dev/null
いくつかのfind
実装(FreeBSD find
とGNUを含むfind
)を使用すると、の-delete
代わりに使用できます-exec rm...
。
エラーが発生する理由はthen
、else
andの間にコマンドがなく、一部のシェル(その構文が由来するBourneシェルから始まる)には少なくとも1つが必要なためです(コメントはコマンドではありません)。これは完全に任意であり、これらのシェルがそれを行う理由はないことに注意してください。その制限はyash
ありzsh
ません(if false; then else echo x; fi
そしてif false; then else fi
、それらでうまく動作します)。
他の人が言ったように、:
(またはfor nothing in; do nothing; done
)のようなnoopコマンドを使用するか、!
キーワードでロジックを逆にすることができます(POSIXシェルでは使用できますが、Bourneシェル:
では使用できません(その使用はそのシェルで一般的でした))。mksh
そして、yash
サポートに起こるif false; then () else echo x; fi
(つまりものの、将来のバージョンで変更される可能性として、私はそれに依存しないでしょう)。
別のアプローチは次のとおりです。
lsof... || {
cmd1
cmd2
}
ただし、1つの違いは、失敗したlsof
場合の全体的な終了ステータスlsof
です。
-exec
、多くの場合に有用である、などであるxargs
時々シェルループが必要とされています、。その場合、while read name
ループが優先オプションです(GNU findを使用するbashでは、両方に-0オプションを使用できます。移植性を考慮して、改行を放棄する必要があります)。
-print0
が-exec printf '%s\0' {} +
(ただし、考慮したい場合を除いて、その出力を処理することはできませんperl
)、find .//.
およびいくつかの後処理を使用すると、の改行をエスケープできますxargs
。でなく、while read
であることに注意してくださいwhile IFS= read -r
。
ファイルが開いている場合は何もしないようにしたいので、を追加する必要:
があります。これはnullコマンドです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'
。
:
、bash-builtinsにリストされている最初のコマンドです。
他の回答はどれも、コマンドが構文エラーを与える理由についての元の質問に実際に対処していません。これは、thenとelseの間にコマンドがないために発生します。
元のコードは次のようになります。
if lsof "$filename" > /dev/null
then
# file is open
else
echo "deleting $filename"
rm "$filename"
fi
問題は、thenとelseの間にコメントがあるが、コメントがコマンドとして扱われないことです。要するに、次のように(構造的に言えば)抱えている問題を書き換えることができます。
$ if true; then else echo; fi
bash: syntax error near unexpected token `else'
elseの前に実際のコマンドを配置することでこの問題を修正できますが、コメントだけでは実行できません。IF-THENセクションでは、空にすることはできません。プレースホルダーが必要な場合は、コロンbuiltinを使用できます。例えば:
$ if true; then :; else echo; fi
単純に置く:
との間の部分に、その後と他のあなたが経験している構文エラーを修正します。
$ ; -bash: syntax error near unexpected token ';'