次のファイルがあります。
$ ls *.png | egrep -i "am|pm"
output-0 11.42.30 AM.png
output-0 5.10.12 PM.png
....
それらを削除したいのですが、このエラーが発生します:
$ ls *.png | egrep -i "am|pm" | while read line; do rm "$line"; done
rm: cannot remove ''$'\033''[0m'$'\033''[01;35moutput-0 11.42.30 AM.png'$'\033''[0m': No such file or directory
rm: cannot remove ''$'\033''[01;35moutput-0 5.10.12 PM.png'$'\033''[0m': No such file or directory
rm: cannot remove ''$'\033''[01;35moutput-1 11.42.30 AM.png'$'\033''[0m': No such file or directory
コードの問題は何ですか?
ls
は、スクリプトおよびコマンドラインでは危険です。 1つの問題は、カラー出力用のANSIエスケープシーケンスである@PerlDuckのコメントに記載されていることです。 find
を使用した別のアプローチをお勧めします
テストファイルを作成する
touch 'output-0 11.42.30 AM.png' 'output-0 5.10.12 PM.png' asdf.png
find
command行が、期待するファイルを見つけることを確認します
find . -type f -iname "*[ap]m*.png"
そしてそれを行う
find . -type f -iname "*[ap]m*.png" -delete
サブディレクトリを検索したくない場合は、-maxdepth 1
を追加してください
find . -maxdepth 1 -type f -iname "*[ap]m*.png" -delete
結果を確認する
ls
名前にam、pm、AM、PMが含まれるファイルは削除する必要がありますが、asdf.png
は削除されません。
本当にでwhile read
ループを使用したい場合は、シェルグロブとprintf
を使用します。
printf '%s\0' *.png | grep -zEi 'am|pm' | while IFS= read -r -d '' line; do echo "$line"; done
ただし、bash
を取得して、直接削除するファイルのリストに展開するには、grep
およびwhile
にパイプする必要はありません。
単純なシェルグロブの使用
rm -- *[ap]m.png *[AP]M.png
または-.PNG
拡張子も一致することを気にしない場合-nocaseglob
オプションを使用する
shopt -s nocaseglob
rm -- *[ap]m.png
拡張グロブを使用して
shopt -s extglob
rm -- *@(AM|PM).png *@(am|pm).png
または
shopt -s extglob nocaseglob
rm -- *@(am|pm).png
--
は、ハイフンで始まるファイル名がある場合に備えて、オプションの終わりを示します-必要に応じて、代わりに./*(am|pm)
のような明示的なディレクトリプレフィックスを持つパターンを使用できます。
削除する前にファイル名をインタラクティブに確認する場合は、-i
または-I
オプションを追加します。