Zakładając, że używasz GNU find(którym prawdopodobnie jesteś, ponieważ -iregexjest to rozszerzenie GNU do POSIXfind ) -regexi -iregexdomyślnie używasz wyrażeń regularnych Emacsa, które nie rozpoznają {3,}. Musisz określić inny typ wyrażeń regularnych za pomocą -regextypeopcji; ponadto musisz dostosować wyrażenie regularne do tego, aby wyrażenie pasowało do pełnej ścieżki:
Dla kompletności, z FreeBSD lub NetBSD find(inna implementacja, która obsługuje -iregex, ale nie twoja, ponieważ .+bez niej nie działałaby -E), napiszesz:
find ~ -iregex '.*[^/]\{3\}\.pdf'
lub:
find -E ~ -iregex '.*[^/]{3}\.pdf'
Bez -Ejest to podstawowe wyrażenie regularne (jak w grep) i -Erozszerzone wyrażenie regularne (jak w grep -E).
Z ast-open's find:
find ~ -iregex '.*[^/]{3}\.pdf'
(to rozszerzone wyrażenia regularne po wyjęciu z pudełka).
Tutaj jest łatwiej dzięki standardowym symbolom wieloznacznym:
find ~ -name '*???.[pP][dD][fF]'
Lub z niektórymi findimplementacjami (te, które obsługują -regexrównież obsługują -iname):
find ~ -iname '*???.pdf'
W przypadku dowolnej liczby znaków zamiast 3tego możesz wrócić do miejsca, w -iregexktórym jest dostępny (patrz odpowiedź @ Stephen Kitt ) lub możesz użyć zshlub ksh93globs:
zsh:
set -o extendedglob # best in ~/.zshrc
printf '%s\n' ~/**/?(#c3,).(#i)pdf(D)
( (D)do rozważenia ukrytych plików i plików w ukrytych katalogach, takich jak z find)
?standardowy symbol wieloznaczny dla dowolnego pojedynczego znaku (np. regexp .)
**/: dowolny poziom podkatalogów (w tym 0)
ksh93:
FIGNORE='@(.|..)' # to consider hidden files
set -o globstar
printf '%s\n' **/{3,}(?).~(i:pdf)
@(x|y): rozszerzony operator symboli wieloznacznych ksh podobny do wyrażenia regularnego (x|y).
FIGNORE: specjalna zmienna, która kontroluje, które pliki są ignorowane przez globs. Po ustawieniu zwykłe ignorowanie ukrytych plików nie jest wykonywane, ale nadal chcemy ignorować wpisy katalogu .i, ..jeśli są obecne.
~(i:...): dopasowanie bez rozróżniania wielkości liter.
Globs mają findtutaj dodatkowe zalety , ponieważ otrzymujesz posortowaną listę (możesz wyłączyć to sortowanie zshza pomocą oNkwalifikatora glob lub użyć innych kryteriów sortowania), a także działać, gdy nazwy plików zawierają sekwencję bajtów, które nie tworzą prawidłowych znaków (dla instancja, w ustawieniach narodowych używających zestawu znaków UTF-8, findpodejście nie zgłasza a $'St\xE9phane Chazelas - CV.pdf, \xE9ponieważ nie jest to znak , który nie jest dopasowywany przez wyrażenie regularne, .symbol wieloznaczny ?lub *GNU find).
Czy to zadziała dla Bash? shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
wjandrea
7
Skąd mam wiedzieć, że są to pliki PDF?
Nie, chyba że zapytasz. Jasne, jestem pedantyczny, ale nie pytałeś o pliki .pdfw ich nazwach . Tylko dlatego, że plik zawiera znaki .pdfw nazwie pliku , nie czyni go plikiem PDF .
W rzeczywistości bądźmy pedantyczni: jeśli cztery ostatnie znaki nazwy pliku to .pdf, to zawsze będzie zawierać więcej niż trzy znaki w nazwie .
Więc robiąc to w niewłaściwy sposób , możesz powiedzieć:
Widzisz ten drugi? W rzeczywistości jest to plik wykonywalny. (Wiem, zmieniłem nazwę). Brakuje też pliku PDF, który mógłbym przysiąc, że był w katalogu Dokumenty ...
$ ls Documents
McLaren 720s Coupe:Order Summary.pdf
Pioneer Premier DEH-P490IB CD Install Manual.PDF
Setup_MagicISO.exe.pdf
Używając tego, -inamemożemy go znaleźć, ale wciąż pojawia się ten plik inny niż PDF.
Tym, co naprawdę chcemy zrobić w tym przypadku, jest sprawdzenie magicznej liczby pliku za pomocą filepolecenia. Jedna opcja generuje typ MIME , który jest łatwiejszy do przeanalizowania. findZapytania staje się proste -name "???*".
Użyjmy separatora dwukropka i poszukaj typu MIME application/pdf, a następnie wyzeruj tę część i wydrukuj wynik. Zauważ, że jeden z moich plików ma dwukropek w nazwie; więc nie mogę po prostu poprosić o 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
Teraz zakończmy, włączając w to pliki PDF o nazwach ai 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
To wszystko. Wiem, że prawdopodobnie zostanę obłąkany za okropnie pedantyczne, ale w mojej pracy z tysiącami woluminów NFS do polowania i wszelkiego rodzaju źle nazwanych plików, chciałbym, żeby więcej ludzi było pedantycznych.
Edytowane w celu dodania: w prawdziwym świecie mógłbym chcieć użyć updatedbdo zbudowania indeksu plików z możliwością przeszukiwania locatezamiast finddo odczytu tego indeksu i parallelzamiast tworzenia xargswątków. Jest to jednak nieco poza zakresem tego pytania. Napisałem to również z prostą twarzą. Dlaczego tak mnie to obchodzi? Być może szukam plików filmowych i dźwiękowych; lub niektóre rodzaje fotografii; lub binarne pliki wykonywalne w katalogu danych projektu.
Jeśli pytający ma taką samą sytuację jak Ty, w której znajdują się pliki PDF, których nazwy nie kończą się na .pdftwoim, pedanteria będzie mile widziana. Ale jest to stosunkowo niezwykła sytuacja (pomimo twojej pracy) i nie mamy żadnego powodu, aby sądzić, że pytający faktycznie musi sobie z tym poradzić, więc uważam, że twoja uwaga, choć ważna, jest trochę rozpraszająca - i myślę, że silny sposób, w jaki to sformułowałeś, wypycha odpowiedź do dziedziny „(prawdopodobnie) nieprzydatnej”. (Oczywiście tylko moja opinia).
David Z
Skoro jesteśmy pedantyczni, jak radziłbyś sobie z plikami PDF, takimi jak poligloty PoC || GTFO ?
Stephen Kitt
@StephenKitt - Nie jestem pewien, o co pytasz, ale jestem zaintrygowany. Wyglądają mi jak zwykłe pliki PDF z niezbyt funkcyjnymi nazwami. Czy te zawiodłyby moje sugerowane rozwiązanie?
Rich
@DavidZ Nie jestem pewien, co powiedzieć. Chodzi mi o to, czy nie jest to trochę pedantyczne, aby podkreślić, że jestem pedantyczny, kiedy już tyle powiedziałem? Oto dlaczego nie jest to „nieprzydatne”: dobrym rozwiązaniem do wyszukiwania plików PDF powinno być elastyczne rozwiązanie do wyszukiwania skryptów, plików binarnych, bibliotek, plików multimedialnych itp. Nie mogę nawet zobaczyć, jak dostosowałbym jeden z inne odpowiedzi na „skompresowane pliki wykonywalne Macha”, ale jestem gotów się uczyć.
Bogaty
1
@ Bogactwo wielu plików PDF to także pliki ZIP, niektóre to także obrazy, a nawet rozruchowe maszyny wirtualne ... (Zobacz linki „spoilerów” w kilku pierwszych kwestiach, aby uzyskać wskazówki; reszta jest udokumentowana w samych plikach PDF.)
Odpowiedzi:
Zakładając, że używasz GNU
find
(którym prawdopodobnie jesteś, ponieważ-iregex
jest to rozszerzenie GNU do POSIXfind
)-regex
i-iregex
domyślnie używasz wyrażeń regularnych Emacsa, które nie rozpoznają{3,}
. Musisz określić inny typ wyrażeń regularnych za pomocą-regextype
opcji; ponadto musisz dostosować wyrażenie regularne do tego, aby wyrażenie pasowało do pełnej ścieżki:Powinieneś także uciec przed,
.
aby pasował do „.” zamiast jakiejkolwiek postaci:Wyrażenie regularne można uprościć, ponieważ obchodzą nas tylko trzy znaki inne niż „/”:
Dla kompletności, z FreeBSD lub NetBSD
find
(inna implementacja, która obsługuje-iregex
, ale nie twoja, ponieważ.+
bez niej nie działałaby-E
), napiszesz:lub:
Bez
-E
jest to podstawowe wyrażenie regularne (jak wgrep
) i-E
rozszerzone wyrażenie regularne (jak wgrep -E
).Z ast-open's
find
:(to rozszerzone wyrażenia regularne po wyjęciu z pudełka).
źródło
Tutaj jest łatwiej dzięki standardowym symbolom wieloznacznym:
Lub z niektórymi
find
implementacjami (te, które obsługują-regex
również obsługują-iname
):W przypadku dowolnej liczby znaków zamiast
3
tego możesz wrócić do miejsca, w-iregex
którym jest dostępny (patrz odpowiedź @ Stephen Kitt ) lub możesz użyćzsh
lubksh93
globs:zsh
:(
(D)
do rozważenia ukrytych plików i plików w ukrytych katalogach, takich jak zfind
)(#cx,y)
jestzsh
równoważnym wyrażeniem regularnym wyrażenia regularnego{x,y}
(#i)
dla bez rozróżniania wielkości liter?
standardowy symbol wieloznaczny dla dowolnego pojedynczego znaku (np. regexp.
)**/
: dowolny poziom podkatalogów (w tym 0)ksh93
:@(x|y)
: rozszerzony operator symboli wieloznacznych ksh podobny do wyrażenia regularnego(x|y)
.FIGNORE
: specjalna zmienna, która kontroluje, które pliki są ignorowane przez globs. Po ustawieniu zwykłe ignorowanie ukrytych plików nie jest wykonywane, ale nadal chcemy ignorować wpisy katalogu.
i,..
jeśli są obecne.{x,y}(z)
jestksh93
odpowiednikiem wyrażenia regularnegoz{x,y}
.~(i:...)
: dopasowanie bez rozróżniania wielkości liter.Globs mają
find
tutaj dodatkowe zalety , ponieważ otrzymujesz posortowaną listę (możesz wyłączyć to sortowaniezsh
za pomocąoN
kwalifikatora glob lub użyć innych kryteriów sortowania), a także działać, gdy nazwy plików zawierają sekwencję bajtów, które nie tworzą prawidłowych znaków (dla instancja, w ustawieniach narodowych używających zestawu znaków UTF-8,find
podejście nie zgłasza a$'St\xE9phane Chazelas - CV.pdf
,\xE9
ponieważ nie jest to znak , który nie jest dopasowywany przez wyrażenie regularne,.
symbol wieloznaczny?
lub*
GNUfind
).źródło
shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
Skąd mam wiedzieć, że są to pliki PDF?
Nie, chyba że zapytasz. Jasne, jestem pedantyczny, ale nie pytałeś o pliki
.pdf
w ich nazwach . Tylko dlatego, że plik zawiera znaki.pdf
w nazwie pliku , nie czyni go plikiem PDF .W rzeczywistości bądźmy pedantyczni: jeśli cztery ostatnie znaki nazwy pliku to
.pdf
, to zawsze będzie zawierać więcej niż trzy znaki w nazwie .Więc robiąc to w niewłaściwy sposób , możesz powiedzieć:
Widzisz ten drugi? W rzeczywistości jest to plik wykonywalny. (Wiem, zmieniłem nazwę). Brakuje też pliku PDF, który mógłbym przysiąc, że był w katalogu Dokumenty ...
Używając tego,
-iname
możemy go znaleźć, ale wciąż pojawia się ten plik inny niż PDF.Tym, co naprawdę chcemy zrobić w tym przypadku, jest sprawdzenie magicznej liczby pliku za pomocą
file
polecenia. Jedna opcja generuje typ MIME , który jest łatwiejszy do przeanalizowania.find
Zapytania staje się proste-name "???*"
.Użyjmy separatora dwukropka i poszukaj typu MIME
application/pdf
, a następnie wyzeruj tę część i wydrukuj wynik. Zauważ, że jeden z moich plików ma dwukropek w nazwie; więc nie mogę po prostu poprosić o awk($2==":"){print $1}
.Teraz zakończmy, włączając w to pliki PDF o nazwach
a
iabc
:To wszystko. Wiem, że prawdopodobnie zostanę obłąkany za okropnie pedantyczne, ale w mojej pracy z tysiącami woluminów NFS do polowania i wszelkiego rodzaju źle nazwanych plików, chciałbym, żeby więcej ludzi było pedantycznych.
Edytowane w celu dodania: w prawdziwym świecie mógłbym chcieć użyć
updatedb
do zbudowania indeksu plików z możliwością przeszukiwanialocate
zamiastfind
do odczytu tego indeksu iparallel
zamiast tworzeniaxargs
wątków. Jest to jednak nieco poza zakresem tego pytania. Napisałem to również z prostą twarzą. Dlaczego tak mnie to obchodzi? Być może szukam plików filmowych i dźwiękowych; lub niektóre rodzaje fotografii; lub binarne pliki wykonywalne w katalogu danych projektu.źródło
.pdf
twoim, pedanteria będzie mile widziana. Ale jest to stosunkowo niezwykła sytuacja (pomimo twojej pracy) i nie mamy żadnego powodu, aby sądzić, że pytający faktycznie musi sobie z tym poradzić, więc uważam, że twoja uwaga, choć ważna, jest trochę rozpraszająca - i myślę, że silny sposób, w jaki to sformułowałeś, wypycha odpowiedź do dziedziny „(prawdopodobnie) nieprzydatnej”. (Oczywiście tylko moja opinia).