Warum gibt find print ein führendes './' aus, wenn keine Pfade angegeben sind?

13

Warum wird findein ./Ergebnis ausgegeben, wenn keine Pfade angegeben wurden?

$ find
./file1
./file2
./file3

Was ist der Grund, warum das nicht ausgedruckt wird?

$ find
file1
file2
file3
nr
quelle

Antworten:

16

Der Grund , warum diese sehen ist , weil die Entwickler von GNU wählten für ein „vernünftiges“ Verhalten zu liefern , wenn kein Pfad angegeben wird. Im Gegensatz dazu gibt POSIX nicht an, dass der Parameter optional ist:find find

Das findDienstprogramm führt die Verzeichnishierarchie von jeder durch den Pfad angegebenen Datei rekursiv ab und wertet einen Booleschen Ausdruck aus, der sich aus den im Abschnitt OPERANDS beschriebenen Primärdaten für jede gefundene Datei zusammensetzt. Jeder Pfadoperand wird unverändert wie angegeben ausgewertet, einschließlich aller nachfolgenden <slash>Zeichen. Alle Pfadnamen für andere Dateien in der Hierarchie müssen aus der Verkettung des aktuellen Pfadoperanden, a, <slash>wenn der aktuelle Pfadoperand nicht mit einem endete, und dem Dateinamen relativ zum Pfadoperanden bestehen. Der relative Teil darf keine Punkt- oder Punkt-Punkt-Komponenten enthalten, kein NachlaufenZeichen und nur einzelne <slash>Zeichen zwischen Pfadnamen-Komponenten.

Sie können den Unterschied in der Übersicht für jeden sehen. GNU hat (wie üblich) optionale Elemente in eckigen Klammern:

find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...]
       [expression]

POSIX gibt zwar nicht an, dass es optional sein kann:

find [-H|-L] path... [operand_expression...]

Im GNU-Programm geschieht dies in ftsfind.c:

  if (leer)
    {
      / *
       * Wir verwenden hier eine temporäre Variable, da einige Aktionen geändert werden
       * der Weg vorübergehend. Wenn wir also eine String-Konstante verwenden,
       * Wir bekommen einen Kernauswurf. Das beste Beispiel dafür ist, wenn wir sagen
       * "find -printf% H" (nicht "find. -printf% H").
       * /
      char defaultpath [2] = ".";
      return find (Standardpfad);
    }

und der "."Einfachheit halber wird ein Literal verwendet. So sehen Sie das gleiche Ergebnis mit

find

und

find .

da (und POSIX damit einverstanden ist) wird der angegebene Pfad verwendet, um die Ergebnisse voranzustellen (siehe oben für die Verkettung ).

Mit ein wenig Arbeit konnte man feststellen, wann das Feature zum ersten Mal hinzugefügt wurde; es war bei der ersten Erstellung von "findutils" im Jahr 1996 vorhanden (siehe find.c):

+  /* If no paths are given, default to ".".  */
+  for (i = 1; i < argc && strchr ("-!(),", argv[i][0]) == NULL; i++)
+    process_top_path (argv[i]);
+  if (i == 1)
+    process_top_path (".");
+
+  exit (exit_status);
+}

Aus dem Changelog für Find 3.8 ging dies anscheinend hervor

Sat Dec 15 19:01:12 1990  David J. MacKenzie  (djm at egypt)

        * find.c (main), util.c (usage): Make directory args optional,
        defaulting to "."
Thomas Dickey
quelle
11

Normalerweise werden die Dateien nachbearbeitet, und in diesem Fall kann es von großem Vorteil sein, den Dateinamen mit zu beginnen ./. Beginnt ein Dateiname mit -, könnte ein nachfolgender Befehl diesen Dateinamen als Option interpretieren. ./vermeidet das.

Stellen Sie sich als Beispiel ein Verzeichnis mit den folgenden Dateien vor:

$ ls
--link  --no-clobber

Stellen Sie sich nun vor, wie dieser Befehl funktionieren würde, wenn die Dateinamen ohne das vorangestellte Zeichen angegeben würden ./:

$ find -type f -exec cp -t ../ {} +

Wir können das Problem an findsich veranschaulichen . Lassen Sie es uns im selben Verzeichnis wie oben ausführen. Die folgenden Arbeiten:

$ find ./*
./--link
./--no-clobber

Folgendes schlägt fehl:

$ find *
find: unknown predicate `--link'
Try 'find --help' for more information.
John1024
quelle
1
Es ergibt Sinn. Aber dann ist da noch die Frage, warum es kein '.' Voranstellt. wenn du rennst find *.
Nr.
@nr Guter Punkt. Ich gehe davon aus, dass es sich für eine Art historische Kompatibilität so verhält. Ich habe der Antwort ein Beispiel hinzugefügt, warum dies unerwünschtes Verhalten ist.
John1024
3
Einige Versionen file fordern den Benutzer auf, einen Pfad anzugeben (wie die BSD-Suche unter OS X). Also muss man normalerweise explizit so etwas sagen find . -type f .... Von da an ist es für einige Versionen von find (wie GNU find) kein großer Schritt, einfach die Standardeinstellung zu übernehmen .und alles andere so zu belassen, wie es ist.
Ilkkachu
1
Der Grund dafür find *, dass das nicht angezeigt wird, .ist, dass *alle Dateien und Ordner aufgelistet, aber ausgeschlossen werden .. Führen Sie echo *in einem Verzeichnis, das nur eine oder zwei Dateien enthält, und Sie werden sehen, dass .das nicht aufgeführt ist. Somit find *arbeitet jede Datei expandiert. Es ist das gleiche, als ob Sie find Desktop/aus dem Home-Verzeichnis sagten . Sie sehen die Ausgabe alsDesktop/foo_bar.txt
Sergiy Kolodyazhnyy
1
@ John1024: Ich glaube, dass Mrigesh und Thomas Dickey die Frage richtig beantwortet haben. Diese Antwort gibt an, warum es praktisch ist, sich so zu findverhalten, wie es ist. Verfügen Sie über maßgebliche Referenzinformationen, um die implizite Behauptung zu untermauern, die findso konzipiert wurde, dass sie sich aus diesem Grund so
G-Man sagt, dass Monica
4

Der findBefehl benötigt Pfad (e) zum Suchen. Wenn wir keine angeben, wird das aktuelle Verzeichnis ( .) als Ausgangspunkt verwendet. Wenn Sie beispielsweise den Pfad übergeben, /tmpwird dies als Ausgangspunkt betrachtet. Und damit die Ergebnisse.

Wenn aktuelles Verzeichnis:

        $ find
or
        $ find .

output:
        ./file1
        ./file2
        ./file3

If- /tmpVerzeichnis:

        $ find /tmp

output:
        /tmp/file4
        /tmp/file5

Wenn abcVerzeichnis unter dem aktuellen Verzeichnis:

        $ find abc

output:
        abc/file6
        abc/file7

Wenn mehrere Verzeichnisse unter dem aktuellen Verzeichnis:

        $ find fu bar

output:
        fu/file10
        fu/file11
        bar/file8
        bar/file9
Mrigesh Priyadarshi
quelle
Ja, ich bin damit einverstanden, dass findein Pfad für die Suche benötigt wird und dass standardmäßig das aktuelle Verzeichnis verwendet wird. Die Frage ist, warum es das führende druckt, ./wenn file.txtgerade das selbe wie ist ./file.txt.
Nr.
1
es ist nicht so, dass find "." Beim Start fügt es tatsächlich alles hinzu, was Sie als Pfad angeben, sei es "/ tmp", "abc" oder ".". Es werden jeweils alle Werte zurückgegeben.
Mrigesh Priyadarshi
-2

Wenn Sie keinen Pfad angeben, findübernimmt der Befehl ${PWD}den Pfad und druckt ihn auf seiner Ausgabe aus. Der Benutzer, der den Pfad nicht angibt, ändert nichts an der Funktionsweise find. Und find funktioniert standardmäßig immer mit Pfaden.

MelBurslan
quelle
1
Aha. Aber wenn du es unter ausführst /tmp, dann $PWDgeht das /tmpnicht ./.
Nr.
Wenn Sie den /tmpfind /tmp./
vorherigen
1
Es ist nicht so, dass ich vorher sehen möchte /tmp . Es ist so, dass es nicht sein kann $PWD.
Nr.
Ich entschuldige ${PWD}mich für die falsche Aussprache
MelBurslan
2
Nein, es wird kein $ PWD vorausgesetzt. Vergleichen Sie die Ausgabe vonfind . , find $PWDund find(ohne Pfad, wenn Ihr Fund unterstützt).
Ilkkachu