' este o eroare ' la încercarea de a trece numele directorului în funcția

În scriptul meu bash, folosesc find pentru a obține numele folderelor prin metacaracter:

for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard}); do stuff=doStuff ${i} done doStuff() { echo ${1} return ${1}"/hello"; } 

Problema este că atunci când fac acest lucru, primesc următoarea eroare (să spunem că $ {i} corespunde „home / me / my_directory”):

line 111: "/home/me/my_directory": is a directory. 

(linia 111 este linia cu „doStuff „)

Am încercat să fac acest lucru, fără rezultat:

for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard}); do stuff=doStuff "${i}" done 

Se pare că programul încearcă să execute director, dar îl vreau doar ca un șir pe care îl pot manipula.

Comentarii

  • Hmmm …. Conform paginii man bash. … Comanda return builtin în bash este folosită pentru a returna un cod EXIT (întreg) nu orice tip de parametru șir.
  • De asemenea, puteți încerca find "${directory}" -mindepth 1 -type d -name "${wildcard}" -print0 | xargs -0 doStuff
  • googleri : o altă sursă excelentă pentru a primi acest mesaj de eroare ge este //a wrong bash line comment în loc de #a correct bash line comment

Răspuns

Citatele și înlocuirea comenzilor sunt problemele dvs. aici.

Problema specifică în care vă confruntați este că shell-ul încearcă să ruleze o comandă numită /home/me/my_directory cu variabila de mediu stuff=doStuff.
Ceea ce doriți cu adevărat (dacă” interpretez corect) este să rulați doStuff cu valoarea $i ca argument, atribuind ieșirea variabilei stuff. Modalitatea de a face acest lucru este să vă înfășurați comanda în $(). De exemplu:

stuff="$(doStuff "$i")" 

Observați cum pun și ghilimele în jurul tuturor. Acest lucru este pentru a preveni shell-ul de a împărți cuvintele pe care nu doriți să le împartă cuvintele (va transforma un singur argument al /foo/bar baz în /foo/bar și baz).

De asemenea, rezultatul funcției dvs. este ceea ce se folosește ca valoare returnată, nu return.

Deoarece ar trebui să utilizați mai multe ghilimele, ar trebui să le adăugați și la orice altceva. Iată o versiune completă a scriptului dvs.:

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 

Trebuie să puneți definiția funcției înainte de a încerca să o utilizați. Shell nu este analizat ca programele compilate, unde trece prin fișier de mai multe ori. Este de sus în jos.
De asemenea, am modificat doStuff pentru a trimite echo către STDERR unde va fi afișat pe terminal, apoi printf trimite către STDOUT unde va fi capturat în variabila stuff.

Rețineți că acest lucru va avea în continuare o problemă dacă oricare dintre directoarele dvs. conține o linie nouă. Cu toate acestea, aceasta este o limitare a shell-ului. Singurul caracter pe care calea unui fișier nu îl poate contain este un NULL char (\0). Cu toate acestea, bash și alte shell-uri nu pot stoca un NULL char într-un șir (nu toate, dar multe. Știu că zsh poate), așa că puteți ” nu îl folosiți ca delimitator.

Comentarii

  • Am vrut doar să adăugăm asta dacă aveți spațiu înainte / după =, se încurcă. de exemplu. MY_VAR = ' / some / path ' este valid, dar MY_VAR = ' / some / calea ' sau MY_VAR = ' / unele / calea ' nu este

Răspuns

Acesta este un efort bun, dar arată că încercați să scrieți bash ca și cum ar fi un limbaj de programare, atunci când este de fapt un limbaj de scriptare simplu. Problema cu construcția dvs. stuff=doStuff arg este că pentru bash nu înseamnă ce credeți că înseamnă. Pentru bash, stuff=doStuff este o atribuire variabilă, iar arg este o comandă. Vă sugerez să citiți următoarele două linkuri:

O versiune funcțională a ceva similar cu ceea ce aveți ar fi

doStuff () { echo "$1/hello" } stuff=$(doStuff "$i") 

Răspuns

Linia care dă eroarea nu face ceea ce crezi că face:

Setează mai întâi variabilele de mediu pe șirul „doStuff” și apoi încearcă să execute $ {i} ca comandă. Și din moment ce $ {i} este un director, acesta eșuează cu mesajul de eroare dat.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *