使用读取行迭代变量

use*_*006 3 command-line bash ls

我有以下文件:

$ ls *.png | egrep -i "am|pm"
output-0 11.42.30 AM.png
output-0 5.10.12 PM.png
....
Run Code Online (Sandbox Code Playgroud)

我想删除它们但收到此错误:

$ 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
Run Code Online (Sandbox Code Playgroud)

我的代码有什么问题?

sud*_*dus 9

ls在脚本和命令行中存在风险。一个问题是@PerlDuck 的评论中所描述的,ANSI 转义序列颜色输出。我会推荐另一种方法find


ste*_*ver 6

如果您真的想以while read这种方式使用循环,请使用 shell glob 并printf使用空分隔符,例如

printf '%s\0' *.png | grep -zEi 'am|pm' | while IFS= read -r -d '' line; do echo "$line"; done
Run Code Online (Sandbox Code Playgroud)

但是,有几种方法可以bash扩展到要直接删除的文件列表 - 无需管道到grepwhile

  1. 使用简单的 shell glob

    rm -- *[ap]m.png *[AP]M.png
    
    Run Code Online (Sandbox Code Playgroud)

    或者 - 如果您不介意匹配.PNG扩展名 - 使用该nocaseglob选项

    shopt -s nocaseglob
    rm -- *[ap]m.png
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用扩展的 glob

    shopt -s extglob
    rm -- *@(AM|PM).png *@(am|pm).png
    
    Run Code Online (Sandbox Code Playgroud)

或者

    shopt -s extglob nocaseglob
    rm -- *@(am|pm).png
Run Code Online (Sandbox Code Playgroud)

--标记选项的结束,以防万一有一些以连字符开头的文件名-你可以使用一种模式有明确的目录前缀一样./*(am|pm),而不是如果你喜欢。

如果要在删除前以交互方式查看文件名,请添加-i-I选项。