Получите дополнение к результату команды ls

Предположим, у меня есть каталог с несколькими файлами, все из которых являются либо двоичными файлами (файлы без объявленных расширений), либо исходными файлами (расширение .c ). Я делаю это:

$ ls

и получить:

README.md hello-world.c hello-world get-name.c get-name

и я хочу перечислять только файлы с определенными расширениями (скажем, как .c и .md ), я делаю:

ls *.c *.md

и все в порядке!

Но что, если теперь я хочу удалить все файлы, не имеющие расширения .c или .md , как я могу это сделать?

Я знаю, как это сделать с файлами, расширения которых мне известны, например:

ls *.c *.md | xargs rm

Но как я могу сообщить командной строке об удалении файлов, которые НЕ соответствуют моим критериям?

2 Solutions collect form web for “Получите дополнение к результату команды ls”

Используйте find :

 find -maxdepth 1 ! -name "*.c" -print0 | xargs -0 ... 

Обратите внимание, что -maxdepth , -print0 , -r и -0 находятся в нескольких реализациях find (были введены GNU find / xargs ), но не указаны POSIX. Другой способ, как сказал Стефан в своем комментарии, использовать -exec действие find – не забудьте использовать форму -exec command {} + , так как она значительно уменьшает количество вызовов command (она должна разрешать синтаксис, где имена файлов размещаются в конце, хотя вам нужно обернуть command внутри вызова sh -c ).

Альтернативно grep вывод ls

 ls | grep -v "\.c$" | xargs ... 

Вы можете фильтровать несколько расширений либо с помощью регулярных выражений:

 ... | grep -v "\.\(c\|md\)$" | ... 

с расширенными регулярными выражениями:

 ... | grep -Ev "\.(c|md)$" | ... 

с параметром fixed strings (не будет соответствовать только в конце имени файла!):

 ... | grep -vF ".c .md" | ... 

или путем цепочки больше grep s:

 ... | grep -v "\.c$" | grep -v "\.md$" | ... 

Тем не менее, find , вероятно, лучший вариант, поскольку с параметром -print0 он обрабатывает все возможные символы в именах файлов, которые могут потребоваться в противном случае (если ваши find и xargs могут работать с строками с завершающим NULL – например, с инструментами GNU) ,

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

 rm -- !(*.c|*.md) 

Эти расширения расширения также доступны в bash после shopt -s extglob и в zsh после setopt kshglob .

Ниже приведен коренной эквивалент zsh:

 setopt extended_glob rm -- ^(*.c|*.md) 

! в extglob «нет». Для вашей первоначальной команды это необходимо:

 rm -- *.c *.md 

Анализ вывода ls является ненадежным и будет разбит на некоторые имена файлов. См. Вики wiki для разбора ls .

  • Перемещение файлов с помощью find + xargs: target не является каталогом?
  • xargs не работает в Linux, поскольку работает в Unix
  • эхом basename под xargs?
  • tcpdump несколько pcaps с xargs
  • zsh "echo SomeText >> ** / filename" в других оболочках
  • Что делает «-t» в команде mv? Пример ниже
  • «Список аргументов слишком длинный»: как мне с этим справиться, не меняя мою команду?
  • Утилита, полезная для работы с памятью, возвращает N первых отсортированных значений
  • Использование xargs для генерации ссылок
  • Пакетная копия в несколько каталогов
  • Отправка списка (текстового файла) файлов и путей в xargs
  • Linux и Unix - лучшая ОС в мире.