Ich möchte verwenden find
, um Dateien in einer Reihe von Ordnern zu finden, die durch Platzhalter eingeschränkt sind, aber im Pfadnamen Leerzeichen enthalten.
Über die Befehlszeile ist dies einfach. Die folgenden Beispiele funktionieren alle.
find te*/my\ files/more -print
find te*/'my files'/more -print
find te*/my' 'files/more -print
Diese finden beispielsweise Dateien in terminal/my files/more
und tepid/my files/more
.
Ich brauche dies jedoch, um Teil eines Skripts zu sein. Was ich brauche ist so etwas:
SEARCH='te*/my\ files/more'
find ${SEARCH} -print
Leider kann ich, was auch immer ich tue, keine Platzhalter und Leerzeichen in einem find
Befehl innerhalb eines Skripts mischen . Das obige Beispiel gibt die folgenden Fehler zurück (beachten Sie die unerwartete Verdoppelung des Backslashs):
find: ‘te*/my\\’: No such file or directory
find: ‘files/more’: No such file or directory
Der Versuch, Anführungszeichen zu verwenden, schlägt ebenfalls fehl.
SEARCH="te*/'my files'/more"
find ${SEARCH} -print
Dies gibt die folgenden Fehler zurück, nachdem die Bedeutung der Anführungszeichen ignoriert wurde:
find: ‘te*/'my’: No such file or directory
find: ‘files'/more’: No such file or directory
Hier ist noch ein Beispiel.
SEARCH='te*/my files/more'
find ${SEARCH} -print
Wie erwartet:
find: ‘te*/my’: No such file or directory
find: ‘files/more’: No such file or directory
Jede Variation, die ich ausprobiert habe, gibt einen Fehler zurück.
Ich habe eine Problemumgehung, die möglicherweise gefährlich ist, weil zu viele Ordner zurückgegeben werden. Ich konvertiere alle Leerzeichen wie folgt in ein Fragezeichen (einstelliges Platzhalterzeichen):
SEARCH='te*/my files/more'
SEARCH=${SEARCH// /?} # Convert every space to a question mark.
find ${SEARCH} -print
Dies entspricht:
find te*/my?files/more -print
Dies gibt nicht nur die richtigen Ordner zurück, sondern auch die terse/myxfiles/more
, die es nicht soll.
Wie kann ich erreichen, was ich versuche? Google hat mir nicht geholfen :(
SEARCH: command not found
der Befehlfind -print
ausgeführt wird.find "${SEARCH}" -print
?te*/'my files'/more
.Antworten:
Der exakt gleiche Befehl sollte in einem Skript gut funktionieren:
Wenn Sie es als Variable benötigen , wird es etwas komplexer:
WARNUNG:
Eine solche Verwendung
eval
ist nicht sicher und kann zur Ausführung von beliebigem und möglicherweise schädlichem Code führen, wenn Ihre Dateinamen bestimmte Zeichen enthalten können. Siehe Bash-FAQ 48 Informationen finden .Es ist besser, den Pfad als Argument zu übergeben:
Ein anderer Ansatz besteht darin,
find
die erweiterten Globbing-Funktionen und Globs von bash vollständig zu vermeiden und zu verwenden:Mit der
globstar
Bash-Option können Sie**
rekursiv übereinstimmen:Verwenden Sie diese Option, damit es sich zu 100% wie das Suchen und Einschließen von Punktdateien (versteckten Dateien) verhält
Sie können sie sogar
echo
direkt ohne die Schleife:quelle
Wie wäre es mit Arrays?
(*)
Wird zu einem Array erweitert, das dem Platzhalter entspricht. Und"${SEARCH[@]}"
erweitert sich in alle Elemente im Array ([@]
), wobei jedes einzeln in Anführungszeichen gesetzt wird.Nachträglich ist mir klar, dass ich dazu in der Lage sein sollte. Etwas wie:
quelle
INPUTPATH='te*/my files/more
undSEARCH=(${INPUTPATH})
. Unabhängig davon, wie unterschiedlich ich dies mache, erhalte ich immer noch ein nicht funktionierendes Ergebnis. Das scheint unmöglich!find
‚s --path
Filter? Es verwendet Platzhalter und muss definitiv nicht erweitert werden.-path
. In den letzten 10 Minuten habe ich jedoch die Antwort herausgefunden: Verwendeneval
! Es scheint einfacher zu sein als-path
.Ich habe endlich die Antwort herausgefunden.
Fügen Sie allen Leerzeichen einen Backslash hinzu:
An dieser Stelle
SEARCH
enthältte*/my\ files/more
.Dann verwenden
eval
.So einfach ist das! Die Verwendung
eval
umgeht die Interpretation${SEARCH}
einer Variablen.quelle