Я хотів би знайти файли PDF, ім’я яких (крім розширення) більше трьох.
$ find ~ -iregex ".{3,}/.pdf"
нічого не повертає, але
$ find ~ -iregex ".+/.pdf"
працює.
Як я можу включити {3,}
варіант?
Я хотів би знайти файли PDF, ім’я яких (крім розширення) більше трьох.
$ find ~ -iregex ".{3,}/.pdf"
нічого не повертає, але
$ find ~ -iregex ".+/.pdf"
працює.
Як я можу включити {3,}
варіант?
Відповіді:
Припустимо, що ви використовуєте 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
).
З аст-відкритом find
:
find ~ -iregex '.*[^/]{3}\.pdf'
(це розширені регулярні вирази поза коробкою).
Тут простіше зі стандартними символами:
find ~ -name '*???.[pP][dD][fF]'
Або з деякими find
реалізаціями (тими, які -regex
також підтримують -iname
):
find ~ -iname '*???.pdf'
Для довільної кількості символів замість 3
цього ви можете скористатися поверненням, -iregex
де це можливо (див. Відповідь @Stephen Kitt ) або ви можете використовувати zsh
або ksh93
глобуси:
zsh
:
set -o extendedglob # best in ~/.zshrc
printf '%s\n' ~/**/?(#c3,).(#i)pdf(D)
( (D)
розглянути приховані файли та файли в прихованих режимах, як і з find
)
(#cx,y)
- це zsh
еквівалент підстановочного символу{x,y}
(#i)
для корпусу нечутливий?
стандартний підстановочний знак для будь-якого окремого символу (наприклад, regexp .
)**/
: будь-який рівень підкаталогів (включаючи 0)ksh93
:
FIGNORE='@(.|..)' # to consider hidden files
set -o globstar
printf '%s\n' **/{3,}(?).~(i:pdf)
@(x|y)
: розширений оператор wildcard ksh схожий на regexp (x|y)
.FIGNORE
: спеціальна змінна, яка контролює, які файли ігноруються глобусами. Якщо встановлено, звичайне ігнорування прихованих файлів не робиться, але ми все ще хочемо ігнорувати записи .
та ..
записи каталогів, де вони є.{x,y}(z)
є ksh93
еквівалентом регулярного вираження z{x,y}
.~(i:...)
: невідчутне до регістру відповідність.Глобуси мають тут деякі додаткові переваги find
в тому, що ви отримуєте відсортований список (ви можете відключити це сортування за zsh
допомогою oN
класифікатора глобусу або використовувати різні критерії сортування), а також працювати, коли назви файлів містять послідовність байтів, які не утворюють дійсних символів (для Наприклад, у локалі, що використовує схему UTF-8, find
підхід не зможе повідомити про $'St\xE9phane Chazelas - CV.pdf
те, \xE9
що те, що не є символом, не відповідає зі знаком регулярного вираження .
або символом підстановки ?
або *
з GNU find
).
shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
Ви цього не зробите, якщо не запитаєте. Звичайно, я буду педантичним, але ви не питали про файли з .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
щоб вводити його. Це дещо поза сферою цього питання. Я це написав і з прямим обличчям. Чому я так дбаю? Я, можливо, шукаю фільми та аудіофайли; або певні типи фотографій; або двійкові виконувані файли в каталозі даних проекту.
.pdf
, ваша педантичність буде дуже вдячна. Але це відносно незвична ситуація (незважаючи на вашу роботу), і ми не маємо жодних підстав вважати, що запитувач насправді має справу з цим, тому я вважаю, що справа, яку ви робите, хоча є дійсною, є дещо відволікаючою - і я думаю, що насильницький спосіб, який ви це виклали, штовхає відповідь у сферу "(мабуть) не корисного". (Моя думка, звичайно.)