' är en katalog ' fel när du försöker överföra katalognamn till funktion

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

  • Hmmm …. Enligt bash mansidan. … Kommandot inbyggt retur i bash används för att returnera en EXIT-kod (heltal) inte någon typ av strängparameter.
  • Du kan också prova find "${directory}" -mindepth 1 -type d -name "${wildcard}" -print0 | xargs -0 doStuff
  • googlers : en annan bra källa för att få detta felmeddelande ge är //a wrong bash line comment istället för #a correct bash line comment

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:

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.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *