I mit bash-script bruger jeg find til at hente mappenavnene med jokertegn:
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard}); do stuff=doStuff ${i} done doStuff() { echo ${1} return ${1}"/hello"; }
Problemet er, at når jeg gør dette, får jeg følgende fejl (lad os sige, at $ {i} svarer til “hjem / mig / min_katalog”):
line 111: "/home/me/my_directory": is a directory.
(linje 111 er linjen med “doStuff “)
Jeg har forsøgt at gøre dette, til ingen nytte:
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard}); do stuff=doStuff "${i}" done
Det er tilsyneladende fordi programmet forsøger at udføre katalog, men jeg vil bare have det som en streng, som jeg kan manipulere.
Kommentarer
Svar
Citater og udskiftning af kommandoer er dine problemer her.
Det specifikke emne, du løber ind i, er fordi skallen prøver at køre en kommando kaldet /home/me/my_directory
med miljøvariablen stuff=doStuff
.
Det du virkelig ønsker (hvis jeg fortolker korrekt) er at køre doStuff
med værdien $i
som et argument, der tildeler output til variablen stuff
. Måden at gøre dette på er at indpakke din kommando i $()
. For eksempel:
stuff="$(doStuff "$i")"
Bemærk hvordan jeg også sætter tilbud omkring alt. Dette er for at forhindre, at skallen orddeler ting, du ikke vil have, at den opdeles i ord (det vil vende et enkelt argument af /foo/bar baz
til /foo/bar
og baz
).
Også output af din funktion er det, der bliver brugt som returværdi, ikke return
.
Da du skulle bruge flere tilbud, skal du også føje dem til alt andet. Her er en komplet version af dit script:
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 skal sætte funktionsdefinitionen, før du prøver at bruge den. Shell er ikke analyseret som kompilerede programmer, hvor den går gennem filen flere gange. Det er top-down.
Jeg har også ændret doStuff
for at sende echo
til STDERR hvor det vil blive vist på terminalen, og derefter sender printf
til STDOUT, hvor det bliver fanget i variablen stuff
.
Bemærk, at dette stadig vil have et problem, hvis nogen af dine mapper indeholder en ny linje. Dette er dog en begrænsning af skallen. Det eneste tegn, en filsti ikke kan contain er en NULL-char (\0
). Bash og andre skaller kan dog ikke gemme en NULL-char i en streng (ikke alle, men mange. Jeg ved, at zsh kan), så du kan ” Brug det ikke som en afgrænser.
Kommentarer
- Vil bare tilføje, at hvis du har plads før / efter
=
, det ødelægger. for eksempel. MY_VAR = ' / some / path ' er gyldig, men MY_VAR = ' / some / sti ' eller MY_VAR = ' / some / sti ' er ikke
Svar
Det er en god indsats, men det viser, at du prøver at skrive bash
som om det var et programmeringssprog, når det faktisk er et simpelt script-sprog. Problemet med din stuff=doStuff arg
konstruktion er, at for bash
betyder det ikke, hvad du mener, det betyder. Til bash
er stuff=doStuff
en variabel tildeling, og arg
er en kommando. Jeg foreslår, at du læser følgende to links:
- Hvordan kan jeg gemme returværdien og / eller output af en kommando i en variabel?
- Hvordan returnerer jeg en streng (eller et stort tal eller et negativt tal) fra en funktion? “return” lader mig kun give et tal fra 0 til 255.
En fungerende version af noget, der ligner det, du har, ville være
doStuff () { echo "$1/hello" } stuff=$(doStuff "$i")
Svar
Linjen, der giver fejlen, gør ikke, hvad du tror, den gør:
Det indstiller først miljøvariabelforretningen til strengen “doStuff” og forsøger derefter at udføre $ {i} som en kommando. Og da $ {i} er et bibliotek, fejler det med den givne fejlmeddelelse.
find "${directory}" -mindepth 1 -type d -name "${wildcard}" -print0 | xargs -0 doStuff
//a wrong bash line comment
i stedet for#a correct bash line comment