Удаление файлов с пробелами в их именах

10

Я пытаюсь удалить все файлы с пробелами в их именах. Я использую следующую команду. Но это дает мне ошибку

Команда: ls | egrep '. ' | xargs rm

Здесь, если я использую только ls | egrep '. 'команду, она дает мне все имя файла с пробелами в именах файлов. Но когда я пытаюсь передать вывод в rm, все пробелы (ведущие или конечные) удаляются. Так что моя команда не выполняется должным образом.

Любые указатели о том, как удалить файл, по крайней мере один пробел в их имени?

Ануй
источник

Ответы:

29

Вы можете использовать стандартное перетаскивание в rmкоманде:

rm -- *\ *

Это удалит любой файл, имя которого содержит пробел; пространство освобождается, поэтому оболочка не интерпретирует его как разделитель. Добавление --позволит избежать проблем с именами файлов, начинающимися с тире (они не будут интерпретироваться как аргументы rm).

Если вы хотите подтвердить каждый файл перед его удалением, добавьте -iопцию:

rm -i -- *\ *
Стивен Китт
источник
4
Вам определенно захочется пройти через это echoсначала, чтобы избежать опечаток. Добавьте echoспереди, и он распечатает все файлы, которые собирается удалить.
Riking
1
Анудж, причина, по которой это вызывает наибольшее количество голосов, заключается в том, что, хотя findэто мощно, иногда вам не нужно убивать курицу из пулемета. Администраторы UNIX, как правило, не прибегают find(например) к «удалению всех файлов, начинающихся с буквы A» ... просто так rm A*. Аналогично, чтобы удалить файлы, содержащие пробелы, rm может сделать эту работу. Другими словами, не обманывайте себя, потому что пространство невидимо и обрабатывается специально оболочкой. Просто избежите этого, как сделал Стивен Китт, и вы можете думать об этом как о любом другом персонаже.
Майк С
14

Я бы не стал разбирать lsвывод

Почему бы и нет :

find . -type f -name '* *' -delete

Нет проблем с rm:-).

Хотя это рекурсивно и удалит все файлы с пробелами в текущем каталоге и вложенных каталогах, как упомянуто в комментариях.

солнцестояние
источник
4
(1) вы можете использовать -name '* *'вместо регулярного выражения; и (2) вы можете использовать -print0 | xargs -0 rm -iдля решения проблемы @ StephenKitt.
Кевин
1
Нет необходимости xargs. Просто используйте-exec rm -i '{}' +
R .. GitHub ОСТАНОВИТЬ ПОМОЩЬ ЛЬДУ
1
@Mhmd У него больше подводных камней, чем у 8-битной игровой консоли. mywiki.wooledge.org/ParsingLs
Daenyth
1
Если вы хотите избежать подкаталогов, используйте find . -maxdepth 1 -name '* *' -delete.
Миккель
1
@BenjaminW. фиксированный ?
SolsTiCe
6

Посмотрите на это Предположим, имя "странный файл"

Решение первое

rm strange\ file

Решение второе

rm "strange file"

Решение третье

ls -i "strange file"

тогда вы видите инод

find . -inum "numberoofinode" -exec rm {} \;

В случае очень странных имен файлов, таких как

!-filename or --filename

использование

rm ./'!-filename'
elbarna
источник
4

От man xargs

xargs читает элементы из стандартного ввода, разделенные пробелами (которые могут быть защищены двойными или одинарными кавычками или обратной косой чертой) или символами новой строки, и выполняет команду (по умолчанию это / bin / echo) один или несколько раз с последующими начальными аргументами по элементам, прочитанным из стандартного ввода. Пустые строки на стандартном вводе игнорируются.

Мы можем (в основном) исправить вашу начальную команду, изменив разделитель xargs на новую строку:

ls | egrep '. ' | xargs -d '\n' rm (не делай этого ... читай дальше)

Но что, если имя файла содержит новую строку?

touch "filename with blanks and newline"

Поскольку имена файлов Unix могут содержать пробелы и символы новой строки , такое поведение по умолчанию часто проблематично; имена файлов, содержащие пробелы и / или символы новой строки, неправильно обрабатываются xargs. В этих ситуациях лучше использовать опцию -0 , которая предотвращает подобные проблемы.

ls это действительно инструмент для непосредственного потребления человеком , вместо этого нам нужно использовать findкоманду, которая может разделять имена файлов нулевым символом ( -print0). Мы также должны указать grep использовать нулевые символы для разделения input ( -z) и output ( -Z). Наконец, мы говорим Xargs также использовать нулевые символы ( -0)

find . -type f -print0 | egrep '. ' -z -Z | xargs -0 rm

anjsimmo
источник
1

Вы можете использовать:

find . -name '* *' -delete
Макс Чжуан
источник
rm - * \ * кажется лучше
Макс Чжуан
Кроме того, это было отражено в комментарии Кевина к ответу solsTiCe.
G-Man говорит: «Восстановите Монику»
-1

Для этого вам понадобится -Zопция grep и -0опция xargs. Но я бы так не поступил ( lsэто не самый подходящий инструмент для работы, есть много проблем с тем, чтобы заставить компьютер читать результаты).

Смотрите другие ответы для лучшего пути.


Также

ls | …эквивалентно ls -d *иecho * | …

Все из которых имеют проблемы. Поэтому не используйте lsтак, используйте решение из другого ответа.

Ctrl-Alt-Делор
источник
Также, ls *когда каналы выводят имена файлов с разделителями. echo(по крайней мере, некоторые echoреализации) расширяет последовательности с обратной косой чертой. grep -Zпредназначен для записи имен файлов с разделением NUL при использовании -l, здесь это не поможет. Если вы имели в виду -z, это тоже не поможет, так как в большинстве lsреализаций отсутствует опция для вывода имен файлов с разделителями NUL. Можно сделать что-то вроде, printf '%s\0' * | grep -z ' ' | xargs -r0 rm -fхотя.
Стефан Шазелас
1
@Kusalananda Я думаю, я это исправил.
Ctrl-Alt-Delor