I mitt bash-skript använder jag hitta för att få mappnamnen med jokertecken:
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard}); do stuff=doStuff ${i} done doStuff() { echo ${1} return ${1}"/hello"; }
Problemet är att när jag gör det får jag följande fel (låt oss säga att $ {i} motsvarar ”hem / mig / min_katalog”):
line 111: "/home/me/my_directory": is a directory.
(rad 111 är raden med ”doStuff ”)
Jag har försökt göra detta, till ingen nytta:
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard}); do stuff=doStuff "${i}" done
Tydligen beror det på att programmet försöker köra katalog, men jag vill bara ha den som en sträng som jag kan manipulera.
Kommentarer
Svar
Citat och kommandosubstitution är dina problem här.
Det specifika problemet du stöter på beror på att skalet försöker köra ett kommando som heter /home/me/my_directory
med miljövariabeln stuff=doStuff
.
Det du verkligen vill (om jag tolkar rätt) är att köra doStuff
med värdet $i
som argument, tilldelar utgången variabeln stuff
. Sättet att göra detta är att slå in ditt kommando i $()
. Till exempel:
stuff="$(doStuff "$i")"
Observera hur jag också lägger citat runt allt. Detta för att förhindra att skalet ordsplitterar saker du inte vill att det ska dela upp ordet (det kommer att göra ett enda argument om /foo/bar baz
till /foo/bar
och baz
).
Även resultatet av din funktion är det som används som returvärdet, inte return
.
Eftersom du borde använda fler citat bör du också lägga till dem till allt annat. Här är en fullständig version av ditt skript:
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
Du måste ange funktionsdefinitionen innan du försöker använda den. Shell analyseras inte som kompilerade program, där den går igenom filen flera gånger. Det är uppifrån och ner.
Jag har också ändrat doStuff
för att skicka echo
till STDERR där det kommer att visas på terminalen och sedan skickar printf
till STDOUT där det kommer att fångas in i variabeln stuff
.
Observera att detta fortfarande kommer att vara ett problem om någon av dina kataloger innehåller en ny rad. Men detta är en begränsning av skalet. Det enda tecknet som en filsökväg inte kan innehåller är en NULL-karaktär (\0
). Men bash och andra skal kan inte lagra en NULL-karaktär i en sträng (inte alla, men många. Jag vet att zsh kan), så du kan ” t använd den som en avgränsare.
Kommentarer
- Ville bara lägga till att om du har utrymme före / efter
=
, det trasslar. t.ex. MY_VAR = ' / some / path ' är giltigt men MY_VAR = ' / some / sökväg ' eller MY_VAR = ' / some / path ' är inte
Svar
Det är en bra ansträngning men det visar att du försöker skriva bash
som om det vore ett programmeringsspråk, när det faktiskt är ett enkelt skriptspråk. Problemet med din stuff=doStuff arg
konstruktion är att för bash
betyder det inte vad du tycker det betyder. Till bash
är stuff=doStuff
en variabel tilldelning och arg
är ett kommando. Jag föreslår att du läser följande två länkar:
- Hur kan jag lagra returvärdet och / eller utdata för ett kommando i en variabel?
- Hur returnerar jag en sträng (eller ett stort antal eller ett negativt tal) från en funktion? ”return” låter mig bara ge ett nummer från 0 till 255.
En fungerande version av något som liknar vad du har skulle vara
doStuff () { echo "$1/hello" } stuff=$(doStuff "$i")
Svar
Raden som ger felet gör inte vad du tror att den gör:
Den ställer först in miljövariabeln till strängen ”doStuff” och försöker sedan köra $ {i} som ett kommando. Och eftersom $ {i} är en katalog, misslyckas det med det angivna felmeddelandet.
find "${directory}" -mindepth 1 -type d -name "${wildcard}" -print0 | xargs -0 doStuff
//a wrong bash line comment
istället för#a correct bash line comment