Как удалить сразу несколько файлов в Bash в Linux?

103

У меня есть этот список файлов на сервере Linux:

abc.log.2012-03-14
abc.log.2012-03-27
abc.log.2012-03-28
abc.log.2012-03-29
abc.log.2012-03-30
abc.log.2012-04-02
abc.log.2012-04-04
abc.log.2012-04-05
abc.log.2012-04-09
abc.log.2012-04-10

Я удалял выбранные файлы журнала один за другим, используя команду, rm -rfсм. Ниже:

rm -rf abc.log.2012-03-14
rm -rf abc.log.2012-03-27
rm -rf abc.log.2012-03-28

Есть ли другой способ удалить выбранные файлы сразу?

user1253847
источник
4
И «Скажем, GNU / Linux, а не только Linux», я слышу чей-то грохот с задних сидений.
Борис Ститницкий
8
Кстати, а почему именно -rf? Это папки? f - сила, r - рекурсивный. Он будет работать, если это всего лишь файл, но будьте осторожны, использование -rf каждый раз, когда вы хотите что-то удалить, очень (очень) (очень очень) опасно. (и вам следует добавить тег «bash», потому что «linux» слишком широк.
Депадо,
@BorisStitnicky - мне любопытно, зачем GNUнужен?
user66001 04
2
@ user66001: Чтобы узнать мнение проекта GNU по этому вопросу: gnu.org/gnu/linux-and-gnu.html . Я не занимаю никакой позиции по этому поводу, по крайней мере, здесь, и здесь не место для обсуждения.
Кейт Томпсон
2
@BorisStitnicky - Не нужно спорить, был совершенно невежественен, и эта ссылка дала мне уровень информации, который я искал +1
user66001 04

Ответы:

160

Bash поддерживает всевозможные подстановочные знаки и расширения.

Ваш точный случай будет обработан расширением фигурных скобок , например:

$ rm -rf abc.log.2012-03-{14,27,28}

Вышеупомянутое будет расширено до одной команды со всеми тремя аргументами и будет эквивалентно вводу:

$ rm -rf abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28

Важно отметить, что это расширение выполняется оболочкой еще до rmзагрузки.

размотать
источник
Не используйте «rm», если вы хотите восстановить файлы в будущем. Вы можете использовать утилиту «rm-trash»: github.com/nateshmbhat/rm-trash
Natesh bhat
76

Используйте подстановочный знак ( *) для сопоставления нескольких файлов.

Например, приведенная ниже команда удалит все файлы с именами, начинающимися с abc.log.2012-03-.

rm -f abc.log.2012-03-*

Я бы рекомендовал запустить ls abc.log.2012-03-*список файлов, чтобы вы могли видеть, что вы собираетесь удалить, перед запуском rmкоманды.

Для получения дополнительной информации см. Справочную страницу Bash о расширении имени файла .

кендырь
источник
Очень полезно, но не запрашивает подтверждения на удаление. Пожалуйста, будьте осторожны.
nuriselcuk
1
@nuriselcuk вы можете добавить -i, чтобы получать подтверждение для каждого удаляемого файла.
Фелипе Ромеро
Сработал как шарм на AWS Ec2-Instance под управлением Amazon Linux 1 :) Спасибо.
Кайл Брайденстайн
41

Если вы хотите удалить все файлы, имена которых соответствуют определенной форме, подстановочный знак (шаблон glob) является наиболее простым решением. Некоторые примеры:

$ rm -f abc.log.*             # Remove them all
$ rm -f abc.log.2012*         # Remove all logs from 2012
$ rm -f abc.log.2012-0[123]*  # Remove all files from the first quarter of 2012

Регулярные выражения более эффективны, чем подстановочные знаки; вы можете скормить вывод grepв rm -f. Например, если некоторые имена файлов начинаются с, "abc.log"а некоторые с "ABC.log", grepвы можете выполнить сопоставление без учета регистра:

$ rm -f $(ls | grep -i '^abc\.log\.')

Это вызовет проблемы, если какое-либо из имен файлов будет содержать забавные символы, включая пробелы. Быть осторожен.

Когда я это делаю, я ls | grep ...сначала запускаю команду и проверяю, дает ли она желаемый результат, особенно если я использую rm -f:

$ ls | grep -i '^abc\.log\.'
(check that the list is correct)
$ rm -f $(!!)

где !!заменяется на предыдущую команду. Или я могу ввести стрелку вверх или Ctrl-P и отредактировать предыдущую строку, чтобы добавить rm -fкоманду.

Предполагается, что вы используете оболочку bash. Некоторые другие оболочки, особенно csh и tcsh, а также некоторые более старые оболочки, производные от sh, могут не поддерживать $(...)синтаксис. Вы можете использовать эквивалентный синтаксис обратной кавычки:

$ rm -f `ls | grep -i '^abc\.log\.'`

$(...)Синтаксис легче читать, и если вы действительно амбициозны это может быть вложенным.

Наконец, если подмножество файлов, которые вы хотите удалить, не может быть легко выражено с помощью регулярного выражения, я часто использую трюк, чтобы перечислить файлы во временный текстовый файл, а затем отредактировать его:

$ ls > list
$ vi list   # Use your favorite text editor

Затем я могу отредактировать listфайл вручную, оставив только те файлы, которые хочу удалить, а затем:

$ rm -f $(<list)

или

$ rm -f `cat list`

(Опять же, это предполагает, что ни одно из имен файлов не содержит забавных символов, особенно пробелов.)

Или при редактировании listфайла я могу добавить rm -f в начало каждой строки, а затем:

$ . ./list

или

$ source ./list

Редактирование файла также дает возможность при необходимости добавлять кавычки, например, переход rm -f foo barна rm -f 'foo bar'.

Кейт Томпсон
источник
8

Просто используйте многострочный выбор в sublime, чтобы объединить все файлы в одну строку и добавить пробел между каждым именем файла, а затем добавить rmв начало списка. Это в основном полезно, когда в именах файлов, которые вы хотите удалить, нет шаблона.

[$]> rm abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28 abc.log.2012-03-29 abc.log.2012-03-30 abc.log.2012-04-02 abc.log.2012-04-04 abc.log.2012-04-05 abc.log.2012-04-09 abc.log.2012-04-10
Энди
источник
Это должен быть принятый ответ, поскольку он явным образом отвечает на поставленный вопрос. Он более дружелюбен к людям, пришедшим сюда из Google.
ATLief
5

Для этого хорошо подойдет подстановочный знак, хотя в целях безопасности было бы лучше использовать подстановочный знак как можно меньше, поэтому что-то вроде этого:

rm -rf abc.log.2012-*

Хотя, судя по всему, это всего лишь отдельные файлы? В рекурсивной опции нет необходимости, если ни один из этих элементов не является каталогом, поэтому лучше не использовать ее в целях безопасности.

лакросс1991
источник
2

Я не гуру Linux, но я считаю, что вы хотите передать свой список выходных файлов по конвейеру xargs rm -rf. Я использовал что-то подобное в прошлом с хорошими результатами. Сначала проверьте образец каталога!

ИЗМЕНИТЬ - Возможно, я неправильно понял, основываясь на других появляющихся ответах. Если вы можете использовать подстановочные знаки, отлично. Я предположил, что ваш исходный список, который вы отображали, был сгенерирован программой, чтобы предоставить вам ваш «выбор», поэтому я подумал, что xargsлучше всего будет использовать конвейер .

Дэйв
источник
-1

если вы хотите удалить сразу все файлы, принадлежащие каталогу. Например: имя вашего каталога - "log", а каталог "log" включает файлы abc.log.2012-03-14, abc.log.2012-03-15, ... и т.д. Вы должны быть выше каталога журналов и:

rm -rf /log/*
Аликане
источник