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

74

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

Firegun
источник
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
Kevin
источник
Некоторые из них могут нуждаться в адаптации в зависимости от того, есть ли у вас папки и что вы хотите с ними делать.
Кевин
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
RJV
источник
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

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

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

rm -rf $(ls -aI ".mydir")
Chetabahana
источник