Я хотів би знайти файли 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, ваша педантичність буде дуже вдячна. Але це відносно незвична ситуація (незважаючи на вашу роботу), і ми не маємо жодних підстав вважати, що запитувач насправді має справу з цим, тому я вважаю, що справа, яку ви робите, хоча є дійсною, є дещо відволікаючою - і я думаю, що насильницький спосіб, який ви це виклали, штовхає відповідь у сферу "(мабуть) не корисного". (Моя думка, звичайно.)