Листинг с `ls` и регулярным выражением

15

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

Я попытался , ls *+([[:digit:]]).txtно это верно для abc12.txtи abc2.txt.

Но мне нужно только получить abc2.txt. Как я могу это сделать?

Есть ли какая-то форма, :digit:которая это сделает?

Web-E
источник
2
Следует отметить , модель действительна только расширенная подстановка endabled: shopt -s extglob.
2012 г.,

Ответы:

20

Как насчет:

ls *[!0-9][0-9].txt

В !начале группы дополняет ее значение.

Как отмечено в комментариях, это делает bash, попробуйте, например:

printf "%s\n" *[!0-9][0-9].txt
Тор
источник
3
Обратите внимание, что bash (то есть ls) не поддерживает регулярные выражения здесь. Это выражения имени файла (Globbing) . Вы можете увидеть разницу уже в своем примере: здесь, *подстановочный знак, которого нет в регулярных выражениях, где вы бы использовали .*для достижения того же. Регулярные выражения намного мощнее, чем глобализация.
Кристофер К.
2

Вопрос задан для регулярных выражений. Bash и, следовательно ls, не поддерживает регулярные выражения здесь. Он поддерживает выражения имен файлов ( Globbing ), форму подстановочных знаков. Регулярные выражения намного мощнее.

Если вы действительно хотите использовать регулярные выражения, вы можете использовать find -regexтак:

find . -maxdepth 1 -regex '\./.*[^0-9][0-9]\.txt'

По умолчанию поиск является рекурсивным, но lsэто не так. Чтобы найти файлы только в текущем каталоге, вы можете отключить рекурсию с помощью -maxdepth 1. Найти совпадения с именем файла с путем, поэтому имена файлов начинаются с, ./если вы запускаете поиск в .. Регулярное выражение начинается с того, \./чтобы справиться с этим. Обратите внимание, что в регулярном выражении .это специальный символ, соответствующий любому символу, но здесь нам действительно нужна точка, поэтому мы избегаем ее с обратной косой чертой. Мы делаем то же самое для точки .txt, потому что в противном случае регулярное выражение также будет соответствовать Atxt. Классы цифр такие же, как и для глобализации, они вам нужны ^вместо того, !чтобы инвертировать класс символов.

Если вы хотите получить вывод ls, то вы можете использовать -exec lsтак:

 find . -maxdepth 1 -regex '\./.*[^0-9][0-9]\.txt' -exec ls -lah {} \;

findподдерживает несколько различных вкусов регулярных выражений. Вы можете указать -regextype, например:

find . -maxdepth 1 -regextype egrep -regex '\./.*[^0-9][0-9]\.txt'

Для меня возможные типы: 'findutils-default', 'awk', 'egrep', 'ed', 'emacs', 'gnu-awk', 'grep', 'posix-awk', 'posix-basic' , 'posix-egrep', 'posix-extended', 'posix-minimal-basic', 'sed' Вы можете запустить, find -regextype helpчтобы узнать, что поддерживается в вашей системе.

Кристофер К.
источник
0

С расширенными глобусами (или bash -O extglobили zsh -o kshglob) ksh, которые вы уже используете, это будет:

ls -d -- ?(*[![:digit:]])[[:digit:]].txt

Или

ls -d -- !(*[[:digit:]])[[:digit:]].txt

Если вы хотите , чтобы соответствовать на a1.txt и2.txt , но не a12.txtни 12.txt.

Однако обратите внимание, что в ksh и bash (если вы не установите failglobопцию для получения поведения, подобного zsh), если этот шаблон не соответствует ни одному файлу, шаблон будет передан буквально ls, и если этот файл (со странным именем) произойдет существует, он будет указан в списке, lsдаже если он не соответствует самому шаблону.

Чтобы включить .2.txt, установите dotglobпараметр в bash, добавьте (D)Глобы классификатор в zshили набор FIGNOREдля !(.|..)в ksh93.

Стефан Шазелас
источник