Предполагая, что вы используете GNU find(которым вы, вероятно, являетесь, поскольку он -iregexявляется расширением GNU для POSIXfind ), -regexи по -iregexумолчанию используются регулярные выражения Emacs, которые не распознаются {3,}. Вы должны указать другой тип регулярных выражений, используя -regextypeопцию; Кроме того, вам нужно настроить регулярное выражение так, чтобы оно совпадало с полным путем:
Для полноты, с FreeBSD или NetBSD find(другая реализация, которая поддерживает -iregex, а не ваша, хотя .+и не будет работать без нее -E), вы должны написать:
find ~ -iregex '.*[^/]\{3\}\.pdf'
или:
find -E ~ -iregex '.*[^/]{3}\.pdf'
Без -E, это основное регулярное выражение (как в grep) и с -Eрасширенным регулярным выражением (как в grep -E).
С ast-open's find:
find ~ -iregex '.*[^/]{3}\.pdf'
(это расширенные регулярные выражения из коробки).
Здесь проще со стандартными подстановочными знаками:
find ~ -name '*???.[pP][dD][fF]'
Или с некоторыми findреализациями (те, которые поддерживают, -regexтакже поддерживают -iname):
find ~ -iname '*???.pdf'
Для произвольного числа символов вместо 3этого, вы можете предпочесть вернуться туда, -iregexгде доступно (см . Ответ @Stephen Kitt ), или вы можете использовать zshили ksh93globs:
zsh:
set -o extendedglob # best in ~/.zshrc
printf '%s\n' ~/**/?(#c3,).(#i)pdf(D)
( (D)чтобы рассматривать скрытые файлы и файлы в скрытых папках, как с find)
?стандартный подстановочный знак для любого отдельного символа (например, регулярное выражение .)
**/: любой уровень подкаталогов (включая 0)
ksh93:
FIGNORE='@(.|..)' # to consider hidden files
set -o globstar
printf '%s\n' **/{3,}(?).~(i:pdf)
@(x|y): расширенный шаблонный символ ksh, похожий на регулярное выражение (x|y).
FIGNORE: специальная переменная, которая контролирует, какие файлы игнорируются глобусами. Когда установлено, обычное игнорирование скрытых файлов не будет сделано, но мы все еще хотим , чтобы игнорировать .и ..запись каталога , где присутствуют.
Глобусы имеют некоторые дополнительные преимущества по сравнению с findтем, что вы получаете отсортированный список (вы можете отключить эту сортировку zshс помощью oNквалификатора глобуса или использовать другие критерии сортировки), а также работать, когда имена файлов содержат последовательность байтов, которые не образуют допустимых символов (для Например, в локали, использующей кодировку UTF-8, findподход не будет сообщать о a $'St\xE9phane Chazelas - CV.pdf, \xE9поскольку не являющийся символом не соответствует регулярному выражению, .подстановочному знаку ?или *GNU find).
Будет ли это работать для Баш? shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
Вандреа
7
Как я узнаю, что это PDF-файлы?
Вы этого не сделаете, если не спросите. Конечно, я педантичен, но вы не спрашивали о файлах с .pdfих именами . Тот факт, что файл содержит символы .pdfв имени файла , не делает его файлом PDF .
На самом деле, давайте будем педантичны во всем этом: если последние четыре символа имени файла .pdf, то в его имени всегда будет более трех символов .
Таким образом, делая это неправильно , вы можете сказать:
Видишь этот второй? Это на самом деле исполняемый файл. (Я знаю, я изменил имя.) И мне также не хватает PDF, который я мог поклясться, был в каталоге документов ...
$ ls Documents
McLaren 720s Coupe:Order Summary.pdf
Pioneer Premier DEH-P490IB CD Install Manual.PDF
Setup_MagicISO.exe.pdf
Таким образом, используя его, -inameмы могли бы найти его, но он все еще включает этот файл, не являющийся файлом PDF.
В этом случае мы действительно хотим проверить магическое число файла с помощью fileкоманды. Одна опция выводит тип MIME , который проще анализировать. findЗапрос становится простым -name "???*".
Давайте используем разделитель двоеточий и ищем MIME-тип application/pdf, затем обнуляем эту часть и выводим результат. Обратите внимание, у одного из моих файлов есть двоеточие в имени; поэтому я не могу просто спросить awk ($2==":"){print $1}.
$ find . -type f -name "???*" -print0|xargs -0 file --mime|awk -F: '($NF~"application/pdf"){OFS=":";$NF="";print}'|sed s/:$//
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF
Теперь давайте закончим, придумав включить файлы PDF с именами aи abc:
$ mkdir Documents/other
$ cp -a Documents/McLaren\ 720s\ Coupe\:Order\ Summary.pdf Documents/other/a
$ cp -a Documents/Pioneer\ Premier\ DEH-P490IB\ CD\ Install\ Manual.PDF Documents/other/abc
$ find . -type f -name "???*" -print0|xargs -0 file --mime|awk -F: '($NF~"application/pdf"){OFS=":";$NF="";print}'|sed s/:$//
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF
./Documents/other/abc
Это все. Я знаю, что мне, вероятно, не понравится, что я ужасно педантичен, но в моей работе с тысячами томов NFS для охоты и всеми видами плохо названных файлов я бы хотел, чтобы больше людей были педантичными.
Отредактировано, чтобы добавить: в реальном мире, я мог бы хотеть использовать updatedbдля создания индекса файла с возможностью поиска, locateвместо того, findчтобы читать этот индекс, а parallelне для того, xargsчтобы продолжить работу. Это несколько выходит за рамки этого вопроса, хотя. Я написал это с невозмутимым лицом тоже. Почему меня это так волнует? Я мог бы искать кино и аудио файлы; или определенные типы фотографий; или двоичные исполняемые файлы в каталоге данных проекта.
Если у спрашивающего такая же ситуация, как и у вас, когда есть PDF-файлы, имена которых не заканчиваются .pdf, тогда ваша педантичность будет высоко оценена. Но это относительно необычная ситуация (несмотря на вашу работу), и у нас нет никаких оснований полагать, что спрашивающему действительно приходится иметь дело с этим, поэтому я считаю, что мысль, которую вы выдвигаете, хотя и действительна, отчасти отвлекает - и я думаю, что силовая формулировка, которую вы сформулировали, толкает ответ в область «(вероятно) бесполезной». (Только мое мнение, конечно.)
Дэвид З
Поскольку мы педантичны, как бы вы справились с PDF-файлами, такими как полиглоты PoC || GTFO ?
Стивен Китт
@StephenKitt - Не уверен, что вы спрашиваете, но я заинтригован. Они выглядят как обычные PDF-файлы для меня с не особо прикольными названиями. Не подойдут ли мои предложенные решения?
Богатый
@DavidZ Я не уверен, что сказать на это. Я имею в виду, не слишком ли педантично указывать, что я педантичен, когда уже сказал это? Вот почему это не «бесполезно»: хорошее решение для поиска PDF-файлов должно быть адаптируемым решением для поиска сценариев, двоичных исполняемых файлов, библиотек, медиа-файлов и т. Д. Я даже не могу понять, как бы я адаптировал один из другие ответы для "сжатых исполняемых файлов Маха", но я готов учиться.
Богатый
1
@ Многие из PDF-файлов также являются ZIP-файлами, некоторые из них также являются изображениями или даже загружаемыми виртуальными машинами ... (см. Ссылки на «спойлеры» в первых нескольких выпусках для подсказок; остальные описаны в самих PDF-файлах.)
Ответы:
Предполагая, что вы используете GNU
find
(которым вы, вероятно, являетесь, поскольку он-iregex
является расширением GNU для POSIXfind
),-regex
и по-iregex
умолчанию используются регулярные выражения Emacs, которые не распознаются{3,}
. Вы должны указать другой тип регулярных выражений, используя-regextype
опцию; Кроме того, вам нужно настроить регулярное выражение так, чтобы оно совпадало с полным путем:Вы также должны избегать,
.
чтобы он соответствовал «.» а не любой персонаж:Регулярное выражение может быть упрощено, так как мы заботимся только о трех символах, отличных от «/»:
Для полноты, с FreeBSD или NetBSD
find
(другая реализация, которая поддерживает-iregex
, а не ваша, хотя.+
и не будет работать без нее-E
), вы должны написать:или:
Без
-E
, это основное регулярное выражение (как вgrep
) и с-E
расширенным регулярным выражением (как вgrep -E
).С ast-open's
find
:(это расширенные регулярные выражения из коробки).
источник
Здесь проще со стандартными подстановочными знаками:
Или с некоторыми
find
реализациями (те, которые поддерживают,-regex
также поддерживают-iname
):Для произвольного числа символов вместо
3
этого, вы можете предпочесть вернуться туда,-iregex
где доступно (см . Ответ @Stephen Kitt ), или вы можете использоватьzsh
илиksh93
globs:zsh
:(
(D)
чтобы рассматривать скрытые файлы и файлы в скрытых папках, как сfind
)(#cx,y)
являетсяzsh
подстановочным эквивалентом регулярного выражения{x,y}
(#i)
без учета регистра?
стандартный подстановочный знак для любого отдельного символа (например, регулярное выражение.
)**/
: любой уровень подкаталогов (включая 0)ksh93
:@(x|y)
: расширенный шаблонный символ ksh, похожий на регулярное выражение(x|y)
.FIGNORE
: специальная переменная, которая контролирует, какие файлы игнорируются глобусами. Когда установлено, обычное игнорирование скрытых файлов не будет сделано, но мы все еще хотим , чтобы игнорировать.
и..
запись каталога , где присутствуют.{x,y}(z)
являетсяksh93
эквивалентом регулярного выраженияz{x,y}
.~(i:...)
: регистронезависимое соответствие.Глобусы имеют некоторые дополнительные преимущества по сравнению с
find
тем, что вы получаете отсортированный список (вы можете отключить эту сортировкуzsh
с помощьюoN
квалификатора глобуса или использовать другие критерии сортировки), а также работать, когда имена файлов содержат последовательность байтов, которые не образуют допустимых символов (для Например, в локали, использующей кодировку UTF-8,find
подход не будет сообщать о a$'St\xE9phane Chazelas - CV.pdf
,\xE9
поскольку не являющийся символом не соответствует регулярному выражению,.
подстановочному знаку?
или*
GNUfind
).источник
shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
Как я узнаю, что это PDF-файлы?
Вы этого не сделаете, если не спросите. Конечно, я педантичен, но вы не спрашивали о файлах с
.pdf
их именами . Тот факт, что файл содержит символы.pdf
в имени файла , не делает его файлом PDF .На самом деле, давайте будем педантичны во всем этом: если последние четыре символа имени файла
.pdf
, то в его имени всегда будет более трех символов .Таким образом, делая это неправильно , вы можете сказать:
Видишь этот второй? Это на самом деле исполняемый файл. (Я знаю, я изменил имя.) И мне также не хватает PDF, который я мог поклясться, был в каталоге документов ...
Таким образом, используя его,
-iname
мы могли бы найти его, но он все еще включает этот файл, не являющийся файлом PDF.В этом случае мы действительно хотим проверить магическое число файла с помощью
file
команды. Одна опция выводит тип MIME , который проще анализировать.find
Запрос становится простым-name "???*"
.Давайте используем разделитель двоеточий и ищем MIME-тип
application/pdf
, затем обнуляем эту часть и выводим результат. Обратите внимание, у одного из моих файлов есть двоеточие в имени; поэтому я не могу просто спросить awk($2==":"){print $1}
.Теперь давайте закончим, придумав включить файлы PDF с именами
a
иabc
:Это все. Я знаю, что мне, вероятно, не понравится, что я ужасно педантичен, но в моей работе с тысячами томов NFS для охоты и всеми видами плохо названных файлов я бы хотел, чтобы больше людей были педантичными.
Отредактировано, чтобы добавить: в реальном мире, я мог бы хотеть использовать
updatedb
для создания индекса файла с возможностью поиска,locate
вместо того,find
чтобы читать этот индекс, аparallel
не для того,xargs
чтобы продолжить работу. Это несколько выходит за рамки этого вопроса, хотя. Я написал это с невозмутимым лицом тоже. Почему меня это так волнует? Я мог бы искать кино и аудио файлы; или определенные типы фотографий; или двоичные исполняемые файлы в каталоге данных проекта.источник
.pdf
, тогда ваша педантичность будет высоко оценена. Но это относительно необычная ситуация (несмотря на вашу работу), и у нас нет никаких оснований полагать, что спрашивающему действительно приходится иметь дело с этим, поэтому я считаю, что мысль, которую вы выдвигаете, хотя и действительна, отчасти отвлекает - и я думаю, что силовая формулировка, которую вы сформулировали, толкает ответ в область «(вероятно) бесполезной». (Только мое мнение, конечно.)