В Linux, как удалить все файлы, кроме шаблона * .txt?


74

Я знаю, как удалить все txtфайлы в текущем каталоге rm *.txt. Кто-нибудь знает, как удалить все файлы в текущем каталоге EXCEPT txtfile?


21
Как всегда, проверяйте данные ответы с помощью безопасной команды, как lsперед тем, как пытаться позвонить rm.
chepner

^ Этот парень не любит жить опасно .. :)
jDub9

Ответы:


111

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

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

Или расширенные возможности bash:

shopt -s extglob
rm *.!(txt)

Или в зш:

setopt extendedglob
rm *~*.txt(.)
#  ||     ^^^ Only plain files
#  ||^^^^^ files ending in ".txt"
#  | \Except
#   \Everything

Некоторые из них могут нуждаться в адаптации в зависимости от того, есть ли у вас папки и что вы хотите с ними делать.
Кевин

1
Не должно *.!(txt)быть !(*.txt)?
Лри

@LauriRanta зависит от того, что находится в папке, на которую мы не получили ответа. Это нормально, как если бы все файлы имели расширения, и rmзадохнулся бы, если бы были папки.
Кевин

У меня проблема с скобками. Когда я использую стиль globbing в скрипте bash, он жалуется на синтаксическую ошибку и круглые скобки. Однако делать это из CLI работает.
CMCDragonkai

1
@izogfif проверьте, что это find . -type f ! -name "*.txt" | xargs -r rmбудет работать в GNU \ xargs. Команда BSD и UNIX xargs может не иметь -r, вы должны проверить свой локальныйman xargs
Ntwobike

10

Есть много способов сделать это. но самый простой способ был бы (bash):

shopt -s extglob
rm !(*.txt)

10

Если вы просто хотите удалить все файлы, кроме «* .txt», вы можете использовать следующую команду:

$ find . -type f ! -name "*.txt" -exec rm -rf {} \;

но если вы также хотите удалить каталоги вместе с файлами, вы можете использовать это:

$ find . ! -name "*.txt" -exec rm -r {} \;


4

Одно решение без find:

mv dir/*.txt otherdir/
rm -r dir
mv otherdir dir

Это должно работать на всех видах снарядов.


3

Вы можете использовать перевернутый grep и xargs

ls | grep -v .txt$| xargs rm

ls | grep -v *.txt | xargs rmработает так же хорошо
Филлипск

@phillipsk grep -v *.txtбудет работать, только если есть только один .txtфайл. Если его нет, grepбудет использоваться *.txtв качестве шаблона; если их больше одного, он будет искать первое имя файла во всех остальных .txtфайлах, игнорируя вывод из ls. (Точные результаты могут зависеть от параметров оболочки.)
JigglyNaga

.txt$будет соответствовать строки, заканчивающиеся txtнезависимо от точки. Потому что grepпринимает в качестве параметра регулярное выражение. Так что файлы a.txtи aatxtи a-txtвсе будут совпадать с этим выражением. Правильное выражение должно быть ls | grep -v \\.txt$ | xargs --no-run-if-empty rm. Для любопытных: если вы хотите поэкспериментировать с выражением, смело используйте это тестовое выражение ls | grep \\.txt$ | xargs --no-run-if-empty echo(примечание: там нет -vфлага и rm=>echo). Примечание 2: вы могли заметить двойную обратную косую черту. Один для регулярных выражений, другой для bash, чтобы избежать косой черты.
Димитрий К

1

Просто сделайте:

rm $(ls -I "*.txt" ) # Удаляет тип файла, кроме * .txt

Аналогичным образом, если необходимо удалить «кроме одного или нескольких типов файлов», выполните:

rm $(ls -I "*.txt" -I "*.pdf" ) # Удаляет типы файлов, кроме * .txt & * .pdf


Добро пожаловать в StackExchange! -IВариант может быть полезен, но видеть , почему не разобрать Ls . И чего | xargsдостигать? Без каких-либо аргументов, он просто работает echoна всех своих входных данных.
JigglyNaga

Чего xargsпредполагается достичь?
дхаг

Спасибо, xargs не был полезен в вышеупомянутом случае, исправили сейчас.
Сурия

0

Это также работает для удаления всех скрытых (точечных) файлов и папок, кроме указанного ( .mydir):

rm -rf $(ls -aI ".mydir")
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.