Используйте строку чтения для итерации по переменным

У меня есть следующие файлы:

$ 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

Какова проблема с моими кодами?

3
задан 2 December 2018 в 19:02

2 ответа

ls опасно в сценариях и командных строках. Одна проблема - то, что описано в комментарии @PerlDuck, escape-последовательностей ANSI для вывода цвета. Я рекомендовал бы другой подход с find

  • Создайте тестовые файлы

    touch 'output-0 11.42.30 AM.png' 'output-0 5.10.12 PM.png' asdf.png
    
  • Проверьте что findкомандная строка находит файлы, которые Вы ожидаете, что это найдет

    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 на имя должен быть удален, но asdf.png не удален.

9
ответ дан 1 December 2019 в 12:56

Если Вы действительно хотите использовать a while read цикл таким образом, затем используйте шарик оболочки и printf с пустыми разделителями, например.

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

Однако существует несколько способов добраться bash расшириться до списка файлов, которые будут удалены непосредственно - без потребности передать по каналу к grep и while:

  1. использование простых шариков оболочки

    rm -- *[ap]m.png *[AP]M.png
    

    или - если Вы не возражаете соответствовать a .PNG расширение также - использование nocaseglob опция

    shopt -s nocaseglob
    rm -- *[ap]m.png
    
  2. использование расширенных шариков

    shopt -s extglob
    rm -- *@(AM|PM).png *@(am|pm).png
    

или

    shopt -s extglob nocaseglob
    rm -- *@(am|pm).png

-- отмечает конец опций, на всякий случай существуют имена файлов, которые начинаются с дефиса - можно использовать шаблон с явным префиксом каталога как ./*(am|pm) вместо этого, если Вы предпочитаете.

Добавьте -i или -I опция, если Вы хотите рассмотреть имена файлов в интерактивном режиме перед удалением.

6
ответ дан 1 December 2019 в 12:56

Другие вопросы по тегам:

Похожие вопросы: