' to katalog ' błąd podczas próby przekazania nazwy katalogu do funkcji

W moim skrypcie basha używam find, aby uzyskać nazwy folderów za pomocą symboli wieloznacznych:

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

Problem polega na tym, że kiedy to robię, otrzymuję następujący błąd (powiedzmy, że $ {i} odpowiada „home / me / my_directory”):

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

(linia 111 to wiersz z „doStuff „)

Próbowałem to zrobić bezskutecznie:

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

Najwyraźniej dzieje się tak, ponieważ program próbuje wykonać katalogu, ale chcę go tylko jako ciąg znaków, którym mogę manipulować.

Komentarze

  • Hmmm …. Zgodnie ze stroną podręcznika bash. … Wbudowane polecenie return w bash służy do zwracania kodu EXIT (liczby całkowitej), a nie żadnego typu parametru ciągu.
  • Możesz także spróbować find "${directory}" -mindepth 1 -type d -name "${wildcard}" -print0 | xargs -0 doStuff
  • Googlers : kolejne świetne źródło otrzymywania tego komunikatu o błędzie ge to //a wrong bash line comment zamiast #a correct bash line comment

Odpowiedź

Cudzysłowy i zastępowanie poleceń to tutaj twoje problemy.

Konkretny problem, z którym się „napotykasz, jest taki, że powłoka próbuje uruchomić polecenie o nazwie /home/me/my_directory ze zmienną środowiskową stuff=doStuff.
To, czego naprawdę chcesz (jeśli interpretuję poprawnie), to uruchomienie doStuff z wartością $i jako argumentem, przypisując wynik do zmiennej stuff. Aby to zrobić, należy umieścić polecenie w $(). Na przykład:

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

Zauważ, że wszystko też zostało cudzysłowem. Ma to na celu zapobieżenie dzieleniu przez powłokę na słowa rzeczy, których nie chcesz, aby dzieliły na słowa (spowoduje to zamianę pojedynczego argumentu /foo/bar baz na /foo/bar i baz).

Również wynik Twojej funkcji jest używany jako wartość zwracana, a nie return.

Ponieważ powinieneś używać więcej cudzysłowów, powinieneś także dodawać je do wszystkiego innego. Oto pełna wersja twojego skryptu:

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 

Musisz umieścić definicję funkcji, zanim spróbujesz jej użyć. Powłoka nie jest analizowana jak skompilowane programy, gdzie przechodzi przez plik kilka razy. Działa z góry na dół.
Zmodyfikowałem także doStuff, aby wysłać echo do STDERR, gdzie zostanie wyświetlony na terminalu, a następnie printf wysyła do STDOUT, gdzie zostanie przechwycony do zmiennej stuff.

Zauważ, że nadal będzie to powodować problem, jeśli którykolwiek z katalogów zawiera znak nowej linii. Jest to jednak ograniczenie powłoki. Jedyny znak, którego ścieżka pliku nie może zawiera to znak NULL (\0). Jednak bash i inne powłoki nie mogą przechowywać znaku NULL w ciągu znaków (nie wszystkie, ale wiele. Wiem, że zsh może), więc możesz ” nie używaj go jako separatora.

Komentarze

  • Chciałem tylko dodać, że jeśli masz spację przed / po =, to psuje. na przykład MY_VAR = ' / some / path ' jest poprawne, ale MY_VAR = ' / some / ścieżka ' lub MY_VAR = ' / some / path ' nie jest

Odpowiedź

To dobry wysiłek, ale pokazuje, że próbujesz napisać bash jakby to był język programowania, podczas gdy w rzeczywistości jest to prosty język skryptowy. Problem z twoją konstrukcją stuff=doStuff arg polega na tym, że bash nie oznacza tego, co myślisz. Do bash, stuff=doStuff to przypisanie zmiennej, a arg to polecenie. Sugeruję przeczytanie następujących dwóch linków:

Działającą wersją czegoś podobnego do tego, co masz, byłaby

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

Odpowiedź

Wiersz podający błąd nie robi tego, co myślisz, że robi:

Najpierw ustawia zmienną środowiskową stuff na łańcuch „doStuff”, a następnie próbuje wykonać $ {i} jako polecenie. A ponieważ $ {i} jest katalogiem, nie powiedzie się z podanym komunikatem o błędzie.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *