finde nicht rekursiv, wenn Datei oben

8

Stellen Sie sich einen Quellbaum vor. Es gibt überall XML-Dateien.

Da sich jedoch eine XYZ.xml im Stammverzeichnis dieses Baums befindet, werden meine XML-Dateien nicht gefunden.

find -iname *.xml

kehrt zurück

./XYZ.xml

anstatt

./XYZ.xml
./a/b/c/bob.xml
./b/d/top.xml
Olivier Toupin
quelle
1
Von man find: Bitte beachten Sie, dass Sie Muster selbstverständlich zitieren sollten, da sonst die Shell alle darin enthaltenen Platzhalterzeichen erweitert.
Artdanil

Antworten:

18
find -iname '*.xml'

Andernfalls Shell erweitert *.xmlzu XYZ.xml, und der Befehl , dass tatsächlich ausgeführt wird ist

find -iname XYZ.xml

Der Grund, warum es funktioniert, wenn das aktuelle Verzeichnis keine XML-Dateien enthält, ist, dass Shells im Allgemeinen Platzhalter nicht erweitern, wenn sie mit nichts übereinstimmen. Im Allgemeinen sollten Sie jederzeit Platzhalter durch ein anderes Programm als die Schale erweitert werden sollen (zB durch find, tar, scp, etc.) müssen Sie sie zitieren , so wird nicht die Shell versuchen , sie selbst zu erweitern.

cjm
quelle
1
Danke, das ist so einfach, aber ich habe mich seit Monaten gefragt, wie ich das umgehen kann. Ich fand das wirklich seltsam und ein sehr inkonsistentes Verhalten, aber jetzt verstehe ich, dass es nicht gefunden wird, sondern Bashs Schuld.
Olivier Toupin
2
Es ist nicht Bashs "Schuld" an sich, sondern Ihre, weil Sie keine Platzhalter zitiert haben, die Sie als Argumente übergeben wollten. Dies gilt für alle Programme, die Shell-Eingaben akzeptieren. Die Shell erweitert sie als Globs, sofern sie nicht in Anführungszeichen gesetzt oder maskiert sind.
Caleb
1
Ich denke, Olivier meinte es in der Bedeutung, dass es eine Frage von bash, nicht von ist find.
Benutzer unbekannt
6

Sie müssen Ihr Argument folgendermaßen zitieren:

find ./ -name '*.xml'

so dass es übergeben wird, um zu finden, anstatt von der Shell erweitert zu werden, und dann übergeben wird, um als erweiterte Version zu finden.

Caleb
quelle
1
Ok, wenn *.xmlalso nichts im aktuellen Verzeichnis übereinstimmt, wird es buchstäblich weitergegeben, weshalb es im anderen Fall funktioniert. Sehr hilfreiche Antwort.
Eric Wilson
1

Platzhalter werden durch die Shell und nicht durch den Befehl erweitert. findist einer der wenigen Befehle, die in ihrer eigenen Zeit einen Wildcard-Abgleich durchführen, der der Shell ähnelt.

Wenn Sie ausführen ls *.xml, wird zuerst die Shell *.xmlauf die Liste der übereinstimmenden Dateien erweitert, z. B. file1.xml file2.xml file3.xml, und dann ruft die Shell lsdie resultierende Liste der Argumente auf file1.xml file2.xml file3.xml. Aus diesem Grund wird dieselbe Liste mit Dateinamen angezeigt echo *.xml, obwohl echonichts über Dateien bekannt ist und es egal ist, ob es sich bei den Argumenten um Dateinamen handelt.

Wenn Sie laufen find . -name "*.xml":

  1. Die Shell analysiert die Befehlszeile, um Sonderzeichen zu erkennen und in Wörter und Puntuation aufzuteilen. Hier gibt es nur eine Liste von Wörtern find, ., -name, *.xmlwo die *zitiert. Da *zitiert wird, ist es ein gewöhnlicher Charakter, was die Shell betrifft.
  2. Die Schale führt den Befehl findmit der angegebenen Liste von Argumenten: ., -name, *.xml.
  3. findsucht nach Dateien, deren Name mit dem Muster *.xmlin einem beliebigen Verzeichnis unter dem aktuellen Verzeichnis übereinstimmt .

Wenn Sie ausführen find . -name *.xmlund keine übereinstimmenden Dateien vorhanden sind *.xml:

  1. Die Shell analysiert die Befehlszeile, um Sonderzeichen zu erkennen und in Wörter und Puntuation aufzuteilen. Hier gibt es nur eine Liste von Wörtern find, ., -name, *.xmlwo der *nicht zitiert.
  2. Da das Wort *.xmlein nicht zitiertes Platzhalterzeichen enthält, führt die Shell die Dateinamengenerierung durch. Da keine übereinstimmenden Dateinamen vorhanden sind, bleibt das Muster nicht erweitert.
  3. Die Schale führt den Befehl findmit der resultierenden Liste von Argumenten, die sind ., -name, *.xml.
  4. findsucht nach Dateien, deren Name mit dem Muster *.xmlin einem beliebigen Verzeichnis unter dem aktuellen Verzeichnis übereinstimmt .

Wenn Sie ausführen find . -name *.xmlund das aktuelle Verzeichnis enthält file1.xml, file2.xmlund file3.xml:

  1. Die Shell analysiert die Befehlszeile, um Sonderzeichen zu erkennen und in Wörter und Puntuation aufzuteilen. Hier gibt es nur eine Liste von Wörtern find, ., -name, *.xmlwo der *nicht zitiert.
  2. Da das Wort *.xmlein nicht in Anführungszeichen gesetztes Platzhalterzeichen enthält, führt die Shell die Dateinamengenerierung durch: *.xmlwird durch die Liste der übereinstimmenden Dateinamen ersetzt.
  3. Die Schale führt den Befehl findmit der resultierenden Liste von Argumenten, die sind ., -name, file1.xml, file2.xml, file3.xml.
  4. findbeschwert sich über einen Syntaxfehler, wenn er erreicht wird file2.xml.

Wenn Sie ausführen find . -name *.xmlund das aktuelle Verzeichnis eine einzelne übereinstimmende Datei enthält file.xml:

  1. Die Shell analysiert die Befehlszeile, um Sonderzeichen zu erkennen und in Wörter und Puntuation aufzuteilen. Hier gibt es nur eine Liste von Wörtern find, ., -name, *.xmlwo der *nicht zitiert.
  2. Da das Wort *.xmlein nicht in Anführungszeichen gesetztes Platzhalterzeichen enthält, führt die Shell die Dateinamengenerierung durch: *.xmlwird durch die Liste der übereinstimmenden Dateinamen ersetzt.
  3. Die Schale führt den Befehl findmit der resultierenden Liste von Argumenten, die sind ., -name, file.xml.
  4. findsieht einen vollkommen gültigen Befehl, aber es ist wahrscheinlich nicht das, was Sie beabsichtigt haben: Es findwird angewiesen, nach Dateien zu suchen, die file.xmlin einem Verzeichnis aufgerufen werden, und nicht nach übereinstimmenden Dateien *.xml.

(Die Shell-Evaluierung und -Erweiterung bietet viele weitere Funktionen. Ich habe nur diejenigen erwähnt, die hier relevant sind.)

(Was ich beschreibe, ist das Standardverhalten der meisten gängigen Shells: sh, bash, dash, ksh, ... Einige Shells können so konfiguriert werden, dass ein Fehler angezeigt wird, anstatt einen Befehl mit nicht erweiterten Platzhaltern auszuführen oder nicht übereinstimmende Platzhalter zu leeren zu erweitern Liste. Keiner von denen würde hier helfen.)

Gilles 'SO - hör auf böse zu sein'
quelle
-1

Dies funktioniert unter Solaris 10:

find /directory-to-search/* -prune -name "*gz"

user32445
quelle
Dies würde nicht nach Namen suchen, die auf enden .xml.
Kusalananda
-2

Bitte versuche:

find ./ -name *.xml
Tok
quelle
Ich habe es gerade versucht, das gleiche Ergebnis.
Eric Wilson
Ich habe es versucht und es funktioniert. Auf GNU Bash 4.2.8
bbaja42
3
Dies funktioniert nicht, wenn der Glob mit etwas im aktuellen Verzeichnis übereinstimmt. Es ist die falsche Syntax! Die *sollten immer zitiert oder entkommen sein, um sie zu finden.
Caleb