Wszyscy mówią, że eval jest zły i powinieneś użyć $() jako zamiennika. Ale natknąłem się na sytuację, w której nieobsługiwany nie jest traktowany tak samo wewnątrz $().
Tło jest to, że byłem zbyt często nagrywany przez ścieżki do plików z miejscami w nich, i tak jak zacytować wszystkie takie ścieżki. Więcej paranoi na temat tego, skąd się biorą wszystkie moje pliki wykonywalne. Jeszcze bardziej paranoiczny, nie ufający sobie i tak jak możliwość wyświetlania utworzonych poleceń, które mam zamiar uruchomić.
Poniżej postaram wariacje na temat używania eval vs. $() i czy nazwa polecenia jest cytowany (bo to mógłby zawierać spacji)
BIN_LS="/bin/ls"
thefile="arf"
thecmd="\"${BIN_LS}\" -ld -- \"${thefile}\""
echo -e "\n Running command '${thecmd}'"
$($thecmd)
Running command '"/bin/ls" -ld -- "arf"'
./foo.sh: line 8: "/bin/ls": No such file or directory
echo -e "\n Eval'ing command '${thecmd}'"
eval $thecmd
Eval'ing command '"/bin/ls" -ld -- "arf"'
/bin/ls: cannot access arf: No such file or directory
thecmd="${BIN_LS} -ld -- \"${thefile}\""
echo -e "\n Running command '${thecmd}'"
$($thecmd)
Running command '/bin/ls -ld -- "arf"'
/bin/ls: cannot access "arf": No such file or directory
echo -e "\n Eval'ing command '${thecmd}'"
eval $thecmd
Eval'ing command '/bin/ls -ld -- "arf"'
/bin/ls: cannot access arf: No such file or directory
$("/bin/ls" -ld -- "${thefile}")
/bin/ls: cannot access arf: No such file or directory
Tak ... to jest mylące. Cytowana ścieżka polecenia jest poprawna wszędzie, z wyjątkiem konstrukcji $()? Krótsza, bardziej bezpośredni przykład:
$ c="\"/bin/ls\" arf"
$ $($c)
-bash: "/bin/ls": No such file or directory
$ eval $c
/bin/ls: cannot access arf: No such file or directory
$ $("/bin/ls" arf)
/bin/ls: cannot access arf: No such file or directory
$ "/bin/ls" arf
/bin/ls: cannot access arf: No such file or directory
Jak można wytłumaczyć prostym $($c)
sprawę?
Nie wycięte łańcuchy są natychmiast oceniane. c = ("/ bin/ls"/bin/l *) robi coś zupełnie innego niż chciał. (spójrz na echo "'$ {c [@]}" ") c = ("/bin/ls ""/bin/l * "), a następnie z = $ (" $ {c [@]} ") zawiedzie. Tablica argumentów nie może być ładnie użyta z $()? – Shenme
Jednak c = ("/ bin/ls" "/ bin/l *") wtedy z = $ ($ {c [@]}) wydaje się działać dobrze. Czy jest to wykonywalna forma $(), którą zamierzałeś mi pokazać? – Shenme