Znajdź wszystkie pliki PDF z co najmniej trzema znakami w nazwie

9

Chciałbym znaleźć pliki PDF, których nazwa (bez rozszerzenia) jest większa niż trzy.

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

nic nie zwraca, ale

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

Pracuje.

Jak mogę włączyć {3,}wariant?

Rachunek różniczkowy
źródło
Jaka długość Długość nazwy pliku? Długość strony?
Ignacio Vazquez-Abrams,

Odpowiedzi:

18

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:

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

Powinieneś także uciec przed, .aby pasował do „.” zamiast jakiejkolwiek postaci:

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

Wyrażenie regularne można uprościć, ponieważ obchodzą nas tylko trzy znaki inne niż „/”:

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

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 -E rozszerzone 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).

Stephen Kitt
źródło
20

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)

    • (#cx,y)jest zshró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:

    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.
    • {x,y}(z)jest ksh93odpowiednikiem wyrażenia regularnego z{x,y}.
    • ~(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).

Stéphane Chazelas
źródło
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ć:

$ find . -type f -name "*???.pdf"
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Setup_MagicISO.exe.pdf

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 "???*".

$ 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

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.

Bogaty
źródło
1
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.)
Stephen Kitt