' je chyba ' adresáře při pokusu o předání názvu adresáře do funkce

V mém bash skriptu používám find k získání názvů složek pomocí zástupných znaků:

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

Problém je v tom, že když to udělám, dostanu následující chyba (řekněme, že $ {i} odpovídá „home / me / my_directory“):

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

(řádek 111 je řádek s „doStuff“ „)

Zkoušel jsem to udělat, ale marně:

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

Je to zřejmě proto, že se program pokouší spustit adresář, ale chci to pouze jako řetězec, se kterým můžu manipulovat.

Komentáře

  • Hmmm …. Podle stránky bash man. … Příkaz return builtin v bash se používá k vrácení kódu EXIT (integer), nikoli jakéhokoli typu parametru řetězce.
  • Můžete také vyzkoušet find "${directory}" -mindepth 1 -type d -name "${wildcard}" -print0 | xargs -0 doStuff
  • googlers : další skvělý zdroj pro získání tohoto chybového hlášení ge je //a wrong bash line comment místo #a correct bash line comment

odpověď

Zde jsou vaše problémy s citacemi a nahrazením příkazů.

Konkrétní problém, na který narazíte, je ten, že se shell pokouší spustit příkaz s názvem /home/me/my_directory s proměnnou prostředí stuff=doStuff.
To, co opravdu chcete (pokud interpretuji správně) je spustit doStuff s hodnotou $i jako argumentu, který přiřadí výstup proměnné stuff. Způsob, jak toho dosáhnout, je zabalit příkaz do $(). Například:

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

Všimněte si, jak také kolem všeho uvádím uvozovky. To zabrání tomu, aby shell rozdělil věci, které nechcete rozdělit na slovo (promění jeden argument /foo/bar baz na /foo/bar a baz).

Výstupem vaší funkce je také to, co se použije jako návratová hodnota, nikoli return.

Protože byste měli používat více uvozovek, měli byste je také přidat ke všem ostatním. Zde je úplná verze vašeho skriptu:

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 

Před použitím funkce musíte definici funkce vložit. Shell není analyzován jako kompilované programy, kde prochází souborem několikrát. Je shora dolů.
Upravil jsem také doStuff tak, aby odeslal echo do STDERR, kde se zobrazí na terminálu, a poté printf odešle do STDOUT, kde bude zachycen do proměnné stuff.

Všimněte si, že to bude mít problém, pokud některý z vašich adresářů obsahuje nový řádek. Jedná se však o omezení prostředí. Jediný znak, k němuž cesta k souboru nemůže contain je NULL char (\0). Nicméně bash a jiné shelly nemohou uložit NULL char do řetězce (ne všechny, ale mnoho. Vím, že zsh může), takže můžete “ nepoužívejte jej jako oddělovač.

Komentáře

  • Chtěl jsem jen dodat, že pokud máte mezeru před / po = to pokazí. např. MY_VAR = ' / some / path ' je platný, ale MY_VAR = ' / some / cesta ' nebo MY_VAR = ' / some / path ' není

Odpověď

To je dobré úsilí, ale ukazuje to, že se snažíte napsat bash jako by to byl programovací jazyk, když je to vlastně jednoduchý skriptovací jazyk. Problém s vaší stuff=doStuff arg konstrukcí spočívá v tom, že to pro bash neznamená to, co si myslíte, že to znamená. K bash je stuff=doStuff přiřazení proměnné a arg je příkaz. Doporučuji přečíst následující dva odkazy:

Pracovní verze něčeho podobného tomu, co máte, by byla

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

Odpověď

Řádek udávající chybu nedělá to, co si myslíte:

Nejprve nastaví proměnné prostředí na řetězec „doStuff“ a poté se pokusí provést příkaz $ {i} jako příkaz. A protože $ {i} je adresář, který s danou chybovou zprávou selže.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *