Suchen Sie alle PDFs mit mindestens drei Zeichen im Namen

9

Ich möchte die PDF-Dateien finden, deren Name (ohne die Erweiterung) größer als drei ist.

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

gibt nichts zurück, aber

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

funktioniert.

Wie kann ich die {3,}Variante aktivieren ?

Infinitesimalrechnung
quelle
Welche Länge? Dateinamenlänge? Seitenlänge?
Ignacio Vazquez-Abrams

Antworten:

18

Angenommen, Sie verwenden GNU find(was Sie wahrscheinlich sind, da -iregexes sich um eine GNU-Erweiterung für POSIX handeltfind ) -regexund -iregexstandardmäßig reguläre Emacs-Ausdrücke, die nicht erkannt werden {3,}. Mit der -regextypeOption müssen Sie einen anderen Typ regulärer Ausdrücke angeben . Darüber hinaus müssen Sie Ihren regulären Ausdruck an die Tatsache anpassen, dass der Ausdruck mit dem vollständigen Pfad übereinstimmt:

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

Sie sollten auch dem entkommen, .damit es mit "." Übereinstimmt. eher als irgendein Charakter:

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

Der reguläre Ausdruck kann vereinfacht werden, da wir uns nur um drei Nicht-"/" -Zeichen kümmern:

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

Der Vollständigkeit halber würden Sie mit FreeBSD oder NetBSD find(eine andere Implementierung, die unterstützt -iregex, aber nicht Ihre, da .+sie dort nicht funktionieren -Ewürde) schreiben:

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

oder:

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

Ohne -Eist das ein grundlegender regulärer Ausdruck (wie in grep) und mit einem -E erweiterten regulären Ausdruck (wie in grep -E).

Mit Ast-Open find:

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

(Das sind erweiterte reguläre Ausdrücke aus der Box).

Stephen Kitt
quelle
20

Hier ist es mit Standard-Platzhaltern einfacher:

find ~ -name '*???.[pP][dD][fF]'

Oder mit einigen findImplementierungen (diejenigen, die -regexauch unterstützen -iname):

find ~ -iname '*???.pdf'

Wenn Sie eine beliebige Anzahl von Zeichen anstelle von 3verwenden möchten, ziehen Sie es möglicherweise vor, auf die -iregexverfügbaren zurückzugreifen (siehe Antwort von @Stephen Kitt ), oder Sie könnten Folgendes verwenden zshoder ksh93globs:

  • zsh::

    set -o extendedglob # best in ~/.zshrc
    printf '%s\n' ~/**/?(#c3,).(#i)pdf(D)
    

    (die (D)versteckten Dateien und Dateien in versteckten Verzeichnissen wie mit zu berücksichtigen find)

    • (#cx,y)ist das zshPlatzhalteräquivalent von regulärem Ausdruck{x,y}
    • (#i) für Groß- und Kleinschreibung nicht berücksichtigen
    • ?Standard-Platzhalter für ein einzelnes Zeichen (wie regulärer Ausdruck .)
    • **/: jede Ebene von Unterverzeichnissen (einschließlich 0)
  • ksh93::

    FIGNORE='@(.|..)' # to consider hidden files
    set -o globstar
    printf '%s\n' **/{3,}(?).~(i:pdf)
    
    • @(x|y): erweiterter ksh-Platzhalteroperator ähnlich wie regulärer Ausdruck (x|y).
    • FIGNORE: Spezielle Variable, die steuert, welche Dateien von Globs ignoriert werden. Wenn diese Option aktiviert ist, werden versteckte Dateien normalerweise nicht ignoriert. Wir möchten jedoch die Einträge .und, ..sofern vorhanden , ignorieren .
    • {x,y}(z)ist ksh93das Äquivalent von regulärem Ausdruck z{x,y}.
    • ~(i:...): Groß- und Kleinschreibung wird nicht berücksichtigt.

Globs haben hier einige zusätzliche Vorteile find: Sie erhalten eine sortierte Liste (Sie können diese Sortierung zshmit dem oNGlob-Qualifikationsmerkmal deaktivieren oder andere Sortierkriterien verwenden) und funktionieren auch, wenn Dateinamen eine Folge von Bytes enthalten, die keine gültigen Zeichen bilden (z In einem Gebietsschema, das den UTF-8-Zeichensatz verwendet, würde der findAnsatz beispielsweise a nicht melden $'St\xE9phane Chazelas - CV.pdf, \xE9da kein Zeichen nicht mit regulärem Ausdruck .oder Platzhalter ?oder *mit GNU übereinstimmt find.

Stéphane Chazelas
quelle
Würde das für Bash funktionieren? shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
Wjandrea
7

Woher weiß ich, dass es sich um PDFs handelt?

Sie tun es nicht, wenn Sie nicht fragen. Sicher, ich bin pedantisch, aber Sie haben nicht nach Dateien.pdf gefragt, deren Namen enthalten sind . Nur weil eine Datei die Zeichen .pdfim Dateinamen enthält, wird sie nicht zu einer PDF-Datei .

Lassen Sie uns diesbezüglich ganz pedantisch vorgehen: Wenn die letzten vier Zeichen des Dateinamens lauten .pdf, enthält der Name immer mehr als drei Zeichen .

Wenn Sie dies also falsch machen , könnten Sie sagen:

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

Sehen Sie den zweiten? Es ist eigentlich eine ausführbare Datei. (Ich weiß, ich habe den Namen geändert.) Und ich vermisse auch ein PDF, von dem ich schwören könnte, dass es sich im Dokumentenverzeichnis befindet ...

$ ls Documents
McLaren 720s Coupe:Order Summary.pdf
Pioneer Premier DEH-P490IB CD Install Manual.PDF
Setup_MagicISO.exe.pdf

Wenn -inamewir also eine verwenden, können wir diese finden, aber diese Nicht-PDF-Datei wird immer noch angezeigt.

Was wir in diesem Fall wirklich tun möchten, ist die magische Nummer der Datei mit dem fileBefehl zu untersuchen. Eine Option gibt den MIME-Typ aus , der einfacher zu analysieren ist. Die findAbfrage wird dann einfach -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

Verwenden wir das Doppelpunkttrennzeichen, suchen nach dem MIME-Typ application/pdf, setzen diesen Teil auf Null und drucken das Ergebnis. Beachten Sie, dass eine meiner Dateien einen Doppelpunkt im Namen hat. also kann ich nicht einfach awk fragen ($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

Beenden Nun lassen sie durch Einfädeln PDF Dateien mit dem Namen enthalten aund 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

Das ist alles. Ich weiß, dass ich mich wahrscheinlich dafür begeistern werde, schrecklich pedantisch zu sein, aber bei meiner Arbeit mit Tausenden von zu jagenden NFS-Bänden und allen Arten von Dateien mit schlechtem Namen wünschte ich mir, mehr Menschen wären pedantisch.

Bearbeitet, um hinzuzufügen: In der realen Welt möchte ich möglicherweise updatedbeinen durchsuchbaren Dateiindex erstellen, locateanstatt finddiesen Index zu lesen und parallelanstatt ihn xargszu fädeln. Das liegt jedoch etwas außerhalb des Rahmens dieser Frage. Das habe ich auch mit ernstem Gesicht geschrieben. Warum kümmert es mich so sehr? Ich suche möglicherweise nach Film- und Audiodateien. oder bestimmte Arten von Fotografien; oder binäre ausführbare Dateien in einem Projektdatenverzeichnis.

Reich
quelle
1
Wenn der Fragesteller die gleiche Situation hat wie Sie, in der es PDF-Dateien gibt, deren Namen nicht enden .pdf, wird Ihre Pedanterie sehr geschätzt. Aber es ist eine relativ ungewöhnliche Situation (trotz Ihres Jobs) und wir haben keinen Grund zu der Annahme, dass der Fragesteller sich tatsächlich damit befassen muss. Ich denke also, dass der Punkt, den Sie machen, zwar gültig, aber irgendwie ablenkend ist - und ich denke, die kraftvolle Art, wie Sie es formuliert haben, drückt die Antwort in den Bereich von "(wahrscheinlich) nicht nützlich". (Nur meine Meinung natürlich.)
David Z
Wie würden Sie mit PDFs wie den PoC || GTFO- Polyglots umgehen, da wir pedantisch sind ?
Stephen Kitt
@ StephenKitt - Unsicher, was Sie fragen, aber ich bin fasziniert. Sie sehen für mich wie gewöhnliche PDFs mit nicht besonders funkigen Namen aus. Würden diese meine vorgeschlagene Lösung verfehlen?
Rich
@ DavidZ Ich bin mir nicht sicher, was ich dazu sagen soll. Ich meine, ist es nicht ein bisschen pedantisch darauf hinzuweisen, dass ich pedantisch bin, wenn ich das schon gesagt habe? Hier ist der Grund, warum es nicht "nicht nützlich" ist: Eine gute Lösung zum Auffinden von PDFs sollte eine anpassbare Lösung zum Auffinden von Skripten, binären ausführbaren Dateien, Bibliotheken, Mediendateien usw. sein. Ich kann nicht einmal erkennen, wie ich eine der Dateien anpassen würde andere Antworten für "komprimierte ausführbare Mach-Dateien", aber ich bin bereit zu lernen.
Rich
1
@Rich viele der PDFs sind auch ZIP-Dateien, einige sind auch Images oder sogar bootfähige virtuelle Maschinen ... (Hinweise finden Sie unter den "Spoiler" -Links in den ersten Ausgaben; der Rest ist in den PDFs selbst dokumentiert.)
Stephen Kitt