Список файлов, не соответствующих шаблону?

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

ls *.jar

Как составить список дополнений узора? т.е. все файлы, не соответствующие * .jar?


person calebds    schedule 15.12.2011    source источник
comment
это, вероятно, не следует обозначать как регулярное выражение, * - это подстановочный знак оболочки, а не регулярное выражение *, которое является нулевым или более квантификатором.   -  person Scott Weaver    schedule 15.12.2011
comment
Хороший момент, хотя я узнал, что использование регулярных выражений, вероятно, является лучшей практикой для получения ожидаемых совпадений.   -  person calebds    schedule 16.12.2011


Ответы (10)


ls | grep -v '\.jar$'

например.

person Michael Krelin - hacker    schedule 15.12.2011
comment
Как можно сделать два типа файлов? - person Dan; 29.11.2012
comment
@ Silver89, например ls | grep -v -e '\.one$' -e '\.two$'. - person Michael Krelin - hacker; 29.11.2012
comment
Не анализируйте вывод ls, спасибо. - person gniourf_gniourf; 06.05.2014
comment
Было бы немного эффективнее использовать ls --ignore = '\. Jar', чтобы избежать вызова другой программы. - person xizdaqrian; 04.07.2016
comment
@xizdaqrian, хороший момент, не знал об этом. Но я считаю, что это только GNU. - person Michael Krelin - hacker; 04.07.2016

Используйте расширенное сопоставление с образцом в стиле egrep.

ls !(*.jar)

Это доступно, начиная с bash-2.02-alpha1. Сначала необходимо включить с помощью

shopt -s extglob

Начиная с bash-4.1-alpha, есть опция конфигурации, позволяющая включить это по умолчанию.

person Christian    schedule 04.09.2012
comment
Ура за упоминание shopt -s extglob! - person Ogre Psalm33; 13.12.2012
comment
Это правильный ответ. Ответ, помеченный как правильный, не использует оболочку напрямую, а использует вспомогательную команду. - person dbn; 09.07.2013
comment
@dbw - Даже если мне больше нравится этот ответ, принятый ответ на вопрос подходит. OP не требует прямого использования оболочки. - person sancho.s ReinstateMonicaCellio; 13.10.2017
comment
egrep-style вводит в заблуждение, поскольку grep имеет дело с регулярными выражениями, а здесь - паттерны оболочки. - person Benjamin W.; 31.01.2018
comment
У меня не получилось. Для длинных списков, возвращающих около 2000 элементов, я получил список аргументов to long. Я предполагаю, что это происходит из-за того, что ветки расширяют внутри себя выходные данные команды. Таким образом, он становится списком аргументов, насчитывающим около 2000 пунктов, что очень много. - person Christoforos; 09.03.2019

Малоизвестное правило расширения bash:

ls !(*.jar)
person ccarton    schedule 15.12.2011
comment
bash:!: событие не найдено. Что мне нужно? - person calebds; 16.12.2011
comment
Попробуйте сначала выполнить shopt -s extglob в командной строке, а затем введите команду. - person Ogre Psalm33; 13.12.2012

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

ls *[!j][!a][!r]

У этого есть некоторые причуды, но, по крайней мере, он совместим с любой оболочкой unix.

person stefanct    schedule 12.09.2014
comment
+1 для соответствия POSIX. Небольшая функция bash / python / ruby ​​в сочетании с псевдонимом, т.е. lsnot может сделать это легко работоспособным. - person Nikkolasg; 12.05.2015
comment
Это не соответствует вещам короче трех символов. - person Benjamin W.; 31.01.2018

С подходящей версией find вы могли бы сделать что-то вроде этого, но это немного перебор:

find . -maxdepth 1 ! -name '*.jar'

find находит файлы. Аргумент . указывает, что вы хотите начать поиск с ., то есть с текущего каталога. -maxdepth 1 сообщает ему, что вы хотите искать только на один уровень в глубину, то есть в текущем каталоге. ! -name '*.jar' ищет все файлы, которые не соответствуют регулярному выражению *.jar.

Как я уже сказал, это немного излишне для этого приложения, но если вы удалите -maxdepth 1, вы можете легко рекурсивно искать все файлы, отличные от jar, или то, что у вас есть.

person Dan Fego    schedule 15.12.2011

Если ваш ls поддерживает это (man ls), используйте параметр --hide=<PATTERN>. В твоем случае:

$> ls --hide=*.jar

Нет необходимости анализировать вывод ls (потому что он очень плохой), и он масштабируется, чтобы не отображать несколько типов файлов. В какой-то момент мне нужно было увидеть, какие файлы, не являющиеся исходными, не объектными и не-libtool, находятся в (загроможденном) каталоге:

$> ls src --hide=*.{lo,c,h,o}

Работал как шарм.

person haavee    schedule 06.09.2018

Другой подход может заключаться в использовании флага ls -I (шаблон игнорирования).

ls -I '*.jar'
person Divyanshu Srivastava    schedule 28.05.2019

А если вы хотите исключить более одного расширения файла, разделите их вертикальной чертой |, например ls test/!(*.jar|*.bar). Давай попробуем:

$ mkdir test
$ touch test/1.jar test/1.bar test/1.foo
$ ls test/!(*.jar|*.bar)
test/1.foo

Глядя на другие ответы, вам может потребоваться shopt -s extglob.

person James Brown    schedule 15.08.2017
comment
Вместо этого вы можете сократить это до !(*.[bj]ar). - person Benjamin W.; 31.01.2018

Одно из решений было бы ls -1|grep -v '\.jar$'

person fge    schedule 15.12.2011
comment
Не анализируйте вывод ls, спасибо. - person gniourf_gniourf; 06.05.2014
comment
@gniourf_gniourf не религиозен в отношении таких правил, как синтаксический анализ ls или использование goto. Иногда эти решения работают лучше всего. - person Jonathan Landrum; 24.07.2014
comment
Это не один из тех случаев; find . -print0 | grep -z '\.jar$' работает лучше, даже если вы не хотите использовать --ignore или расширенную подстановку Bash. Тем не менее, большинство людей не хотят читать всю статью, чтобы понять правило или то, что им следует делать, и вы можете подобрать простое объяснение и рекомендацию типа «это не работает в крайних случаях». ; используйте вместо них find -print0 и grep -z »в комментарии. - person Daniel H; 07.01.2017

Некоторые упомянутые варианты этой формы:

ls -d *.[!j][!a][!r]

Но, похоже, это работает только с bash, в то время как это работает как с bash, так и с zsh:

ls -d *.[^j][^a][^r]
person Thomas Debesse    schedule 24.04.2021