In meinem Bash-Skript verwende ich find, um die Ordnernamen per Platzhalter abzurufen:
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard}); do stuff=doStuff ${i} done doStuff() { echo ${1} return ${1}"/hello"; }
Das Problem ist, dass ich dies bekomme, wenn ich dies tue Der folgende Fehler (sagen wir, dass $ {i} „home / me / my_directory“ entspricht):
line 111: "/home/me/my_directory": is a directory.
(Zeile 111 ist die Zeile mit „doStuff“ „)
Ich habe dies erfolglos versucht:
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard}); do stuff=doStuff "${i}" done
Anscheinend liegt es daran, dass das Programm versucht, das auszuführen Verzeichnis, aber ich möchte es nur als Zeichenfolge, die ich bearbeiten kann.
Kommentare
- Hmmm …. Laut der Bash-Manpage. … Der Befehl return builtin in bash wird verwendet, um einen EXIT-Code (Ganzzahl) zurückzugeben, der kein String-Parameter ist.
- Sie können auch
find "${directory}" -mindepth 1 -type d -name "${wildcard}" -print0 | xargs -0 doStuff
- Googler : Eine weitere großartige Quelle, um diese Fehlermeldung zu erhalten ge ist
//a wrong bash line comment
anstelle von#a correct bash line comment
Antwort
Anführungszeichen und Befehlsersetzung sind hier Ihre Probleme.
Das spezifische Problem, auf das Sie stoßen, besteht darin, dass die Shell versucht, einen Befehl mit dem Namen mit der Umgebungsvariablen stuff=doStuff
.
Was Sie wirklich wollen (wenn ich richtig interpretiere), ist doStuff
mit dem Wert $i
als Argument, wobei die Ausgabe der Variablen stuff
zugewiesen wird. Die Möglichkeit dazu besteht darin, Ihren Befehl in $()
zu verpacken. Zum Beispiel:
stuff="$(doStuff "$i")"
Beachten Sie, wie ich auch alles in Anführungszeichen setze. Dies soll verhindern, dass die Shell Wörter aufteilt, von denen Sie nicht möchten, dass sie Wörter aufteilen (es wird ein einzelnes Argument von /foo/bar baz
in /foo/bar
und baz
).
Auch die Ausgabe Ihrer Funktion wird als Rückgabewert verwendet, nicht return
.
Da Sie mehr Anführungszeichen verwenden sollten, sollten Sie diese auch zu allem anderen hinzufügen. Hier ist eine vollständige Version Ihres Skripts:
doStuff() { echo "${1}" >&2 printf "%s/hello" "$1"; } IFS=$"\n" for i in $(find "${directory}" -mindepth 1 -type d -name "${wildcard}"); do stuff="$(doStuff "${i}")" done
Sie müssen die Funktionsdefinition eingeben, bevor Sie versuchen, sie zu verwenden. Shell wird nicht wie kompilierte Programme analysiert, bei denen die Datei mehrmals durchlaufen wird. Sie ist von oben nach unten.
Ich habe auch doStuff
geändert, um das echo
an STDERR, wo es auf dem Terminal angezeigt wird, und dann sendet die printf
an STDOUT, wo es in der Variablen stuff
.
Beachten Sie, dass dies immer noch ein Problem darstellt, wenn eines Ihrer Verzeichnisse eine neue Zeile enthält. Dies ist jedoch eine Einschränkung der Shell. Das einzige Zeichen, das ein Dateipfad nicht kann enthalten ist ein NULL-Zeichen (\0
). Bash und andere Shells können jedoch kein NULL-Zeichen in einer Zeichenfolge speichern (nicht alle, aber viele. Ich weiß, dass zsh kann), also können Sie “ Verwenden Sie es nicht als Trennzeichen.
Kommentare
- Ich wollte das nur hinzufügen, wenn Sie vor / nach
=
, es bringt es durcheinander. z.B. MY_VAR = ' / some / path ' ist gültig, aber MY_VAR = ' / some / Pfad ' oder MY_VAR = ' / some / Pfad ' ist nicht
Antwort
Das ist eine gute Anstrengung, aber es zeigt, dass Sie versuchen, bash
als wäre es eine Programmiersprache, wenn es sich tatsächlich um eine einfache Skriptsprache handelt. Das Problem mit Ihrer stuff=doStuff arg
-Konstruktion besteht darin, dass bash
nicht bedeutet, was Sie denken, dass es bedeutet. Für bash
ist stuff=doStuff
eine Variablenzuweisung und arg
ein Befehl. Ich schlage vor, Sie lesen die folgenden zwei Links:
- Wie kann ich den Rückgabewert und / oder die Ausgabe eines Befehls in einer Variablen speichern?
- Wie gebe ich eine Zeichenfolge (oder eine große Zahl oder eine negative Zahl) von einer Funktion zurück? Mit „return“ kann ich nur eine Zahl zwischen 0 und 255 angeben.
Eine funktionierende Version von etwas ähnlichem wie dem, was Sie haben, wäre
doStuff () { echo "$1/hello" } stuff=$(doStuff "$i")
Antwort
Die Zeile mit dem Fehler macht nicht das, was Sie denken:
Es setzt zuerst die Umgebungsvariablen auf die Zeichenfolge „doStuff“ und versucht dann, $ {i} als Befehl auszuführen. Und da $ {i} ein Verzeichnis ist, schlägt dies mit der angegebenen Fehlermeldung fehl.