Найдите все PDF-файлы, содержащие не менее трех символов в названии

9

Я хотел бы найти файлы PDF, чье имя (исключая расширение) больше трех.

$ find ~ -iregex ".{3,}/.pdf"

ничего не возвращает, но

$ find ~ -iregex ".+/.pdf"

работает.

Как я могу включить {3,}вариант?

Исчисление
источник
Какой длины? Длина имени файла? Длина страницы?
Игнасио Васкес-Абрамс

Ответы:

18

Предполагая, что вы используете GNU find(которым вы, вероятно, являетесь, поскольку он -iregexявляется расширением GNU для POSIXfind ), -regexи по -iregexумолчанию используются регулярные выражения Emacs, которые не распознаются {3,}. Вы должны указать другой тип регулярных выражений, используя -regextypeопцию; Кроме того, вам нужно настроить регулярное выражение так, чтобы оно совпадало с полным путем:

find ~ -regextype posix-extended -iregex '.*/[^/]{3,}.pdf'

Вы также должны избегать, .чтобы он соответствовал «.» а не любой персонаж:

find ~ -regextype posix-extended -iregex '.*/[^/]{3,}\.pdf'

Регулярное выражение может быть упрощено, так как мы заботимся только о трех символах, отличных от «/»:

find ~ -regextype posix-extended -iregex '.*[^/]{3}\.pdf'

Для полноты, с 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'

(это расширенные регулярные выражения из коробки).

Стивен Китт
источник
20

Здесь проще со стандартными подстановочными знаками:

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)

    • (#cx,y)является zshподстановочным эквивалентом регулярного выражения{x,y}
    • (#i) без учета регистра
    • ?стандартный подстановочный знак для любого отдельного символа (например, регулярное выражение .)
    • **/: любой уровень подкаталогов (включая 0)
  • ksh93:

    FIGNORE='@(.|..)' # to consider hidden files
    set -o globstar
    printf '%s\n' **/{3,}(?).~(i:pdf)
    
    • @(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поскольку не являющийся символом не соответствует регулярному выражению, .подстановочному знаку ?или *GNU find).

Стефан Шазелас
источник
Будет ли это работать для Баш? shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
Вандреа
7

Как я узнаю, что это PDF-файлы?

Вы этого не сделаете, если не спросите. Конечно, я педантичен, но вы не спрашивали о файлах с .pdfих именами . Тот факт, что файл содержит символы .pdfв имени файла , не делает его файлом PDF .

На самом деле, давайте будем педантичны во всем этом: если последние четыре символа имени файла .pdf, то в его имени всегда будет более трех символов .

Таким образом, делая это неправильно , вы можете сказать:

$ find . -type f -name "*???.pdf"
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Setup_MagicISO.exe.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 "???*".

$ find . -type f -name "???*" -print0|xargs -0 file --mime
./.bash_history:                                              text/plain; charset=us-ascii
./.bash_logout:                                               text/plain; charset=us-ascii
./.bashrc:                                                    text/plain; charset=us-ascii
./.profile:                                                   text/plain; charset=us-ascii
./Documents/McLaren 720s Coupe:Order Summary.pdf:             application/pdf; charset=binary
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF: application/pdf; charset=binary
./Documents/Setup_MagicISO.exe.pdf:                           application/x-dosexec; charset=binary
./Downloads/Setup_MagicISO.exe:                               application/x-dosexec; charset=binary
./Downloads/WindowsUpdate.diagcab:                            application/vnd.ms-cab-compressed; charset=binary

Давайте используем разделитель двоеточий и ищем 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чтобы продолжить работу. Это несколько выходит за рамки этого вопроса, хотя. Я написал это с невозмутимым лицом тоже. Почему меня это так волнует? Я мог бы искать кино и аудио файлы; или определенные типы фотографий; или двоичные исполняемые файлы в каталоге данных проекта.

Богатые
источник
1
Если у спрашивающего такая же ситуация, как и у вас, когда есть PDF-файлы, имена которых не заканчиваются .pdf, тогда ваша педантичность будет высоко оценена. Но это относительно необычная ситуация (несмотря на вашу работу), и у нас нет никаких оснований полагать, что спрашивающему действительно приходится иметь дело с этим, поэтому я считаю, что мысль, которую вы выдвигаете, хотя и действительна, отчасти отвлекает - и я думаю, что силовая формулировка, которую вы сформулировали, толкает ответ в область «(вероятно) бесполезной». (Только мое мнение, конечно.)
Дэвид З
Поскольку мы педантичны, как бы вы справились с PDF-файлами, такими как полиглоты PoC || GTFO ?
Стивен Китт
@StephenKitt - Не уверен, что вы спрашиваете, но я заинтригован. Они выглядят как обычные PDF-файлы для меня с не особо прикольными названиями. Не подойдут ли мои предложенные решения?
Богатый
@DavidZ Я не уверен, что сказать на это. Я имею в виду, не слишком ли педантично указывать, что я педантичен, когда уже сказал это? Вот почему это не «бесполезно»: хорошее решение для поиска PDF-файлов должно быть адаптируемым решением для поиска сценариев, двоичных исполняемых файлов, библиотек, медиа-файлов и т. Д. Я даже не могу понять, как бы я адаптировал один из другие ответы для "сжатых исполняемых файлов Маха", но я готов учиться.
Богатый
1
@ Многие из PDF-файлов также являются ZIP-файлами, некоторые из них также являются изображениями или даже загружаемыми виртуальными машинами ... (см. Ссылки на «спойлеры» в первых нескольких выпусках для подсказок; остальные описаны в самих PDF-файлах.)
Стивен Китт