' on hakemisto ' -virhe yritettäessä siirtää hakemiston nimi funktioon

Bash-komentosarjassa käytän hakua hakemaan kansionimet jokerimerkillä:

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

Ongelmana on, että kun teen tämän, saan seuraava virhe (sanotaan, että $ {i} vastaa ”home / me / my_directory”):

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

(rivi 111 on ”doStuff” -rivi ”)

Olen yrittänyt tehdä tämän, turhaan:

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

Ilmeisesti se johtuu siitä, että ohjelma yrittää suorittaa hakemistoa, mutta haluan sen vain merkkijonona, jota voin muokata.

Kommentit

  • Hmmm …. bashin man-sivun mukaan. … bashin palautettua sisäänrakennettua komentoa käytetään palauttamaan EXIT-koodi (kokonaisluku) eikä minkään tyyppisiä merkkijonoparametreja.
  • Voit myös kokeilla find "${directory}" -mindepth 1 -type d -name "${wildcard}" -print0 | xargs -0 doStuff
  • googlers : toinen hyvä lähde tämän virheen saamiseksi ge on //a wrong bash line comment #a correct bash line comment

vastaus

Lainausmerkit ja komentojen korvaaminen ovat kysymyksesi tässä.

Erityinen ongelma, johon törmäät, johtuu siitä, että kuori yrittää suorittaa komentoa nimeltä /home/me/my_directory ympäristömuuttujan stuff=doStuff kanssa.
Mitä todella haluat (jos tulkitsen oikein) on ajaa doStuff, jonka arvo on $i argumenttina, määrittäen lähdön muuttujalle stuff. Tapa tehdä tämä on kietoa komento $(). Esimerkiksi:

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

Huomaa, kuinka laittoin myös lainauksia kaiken ympärille. Tämän tarkoituksena on estää kuorta jakamasta asioita, joita et halua sen jakavan (se ”muuttaa yhden argumentin /foo/bar baz osaksi /foo/bar ja baz).

Myös funktion lähdössä käytetään paluuarvoa, ei return.

Koska sinun pitäisi käyttää enemmän lainausmerkkejä, sinun on lisättävä ne myös kaikkeen muuhun. Tässä on komentosarjosi täydellinen versio:

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 

Funktion määritelmä on laitettava ennen kuin yrität käyttää sitä. Shelliä ei jäsennellä kuten käännettyjä ohjelmia, missä se käy tiedoston läpi useita kertoja. Se on ylhäältä alas.
Olen myös muokannut doStuff -kuvaketta lähettämään echo STDERR: lle, missä se näytetään päätelaitteessa, ja sitten printf lähettää STDOUT: lle, missä se kaapataan muuttujaan stuff.

Huomaa, että tässä on edelleen ongelma, jos jokin hakemistoistasi sisältää uuden rivin. Tämä on kuitenkin kuoren rajoitus. Ainoa merkki, jota tiedostopolku ei voi include on NULL-merkki (\0). Bash ja muut kuoret eivät kuitenkaan voi tallentaa NULL-merkkiä merkkijonoon (eivät kaikki, mutta monet. Tiedän, että zsh voi), joten voit ” t käytä sitä erottimena.

Kommentit

  • Halusin vain lisätä, että jos sinulla on tilaa ennen / jälkeen =, se sekoittaa. esimerkiksi. MY_VAR = ' / some / path ' on kelvollinen, mutta MY_VAR = ' / some / polku ' tai MY_VAR = ' / some / path ' ei ole

Vastaus

Se on hyvä ponnistus, mutta se osoittaa, että yrität kirjoittaa bash ikään kuin se olisi ohjelmointikieli, kun se on itse asiassa yksinkertainen komentosarjakieli. stuff=doStuff arg -rakenteen ongelmana on, että bash se ei tarkoita sitä, mitä luulet sen tarkoittavan. Kohteeseen bash stuff=doStuff on muuttujan määritys ja arg on komento. Ehdotan, että luet seuraavat kaksi linkkiä:

Toimiva versio jotain samanlaista kuin sinulla olisi

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

Vastaa

Virheen antava rivi ei tee sitä mitä luulet tekevänsä:

Se asettaa ensin ympäristömuuttujatiedot merkkijonoksi ”doStuff” ja yrittää sitten suorittaa $ {i} -komennon. Ja koska $ {i} on hakemisto, se epäonnistuu annetulla virheilmoituksella.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *