Czy jest jakiś sposób na przekierowanie stdout i stderr przez zmienną, na przykład poprzez dodanie opcji poleceń w skrypcie?
Na przykład mam skrypt:
#!/bin/bash -x
TEST=">/dev/null 2>&1"
OPT='-p -v'
mkdir $OPT 123/123/123 $TEST
Widzę, że OPT został zastąpiony -p
bez żadnych problemów i bash interpretuje to jako opcję. Ale przekierowanie interpretuje jako nazwę katalogów.
$ ./test.sh
+ TEST='>/dev/null 2>&1'
+ OPT='-p -v'
+ mkdir -p -v 123/123/123 '>/dev/null' '2>&1'
mkdir: created directory `123/123'
mkdir: created directory `123/123/123'
mkdir: created directory `>/dev'
mkdir: created directory `>/dev/null'
mkdir: created directory `2>&1'
Czy jest jakikolwiek sposób powiedzieć bash, że $ VAR to przekierowanie, a nie nazwy katalogów.
PS. Być może jestem w złym kierunku, ale chcę tworzyć opcjonalne pełne lub nieokreślone dane wyjściowe z mojego skryptu. Ale potrzebuję trochę danych wyjściowych nawet w trybie nieokreślonym, dlatego nie mogę po prostu przekierować całego stdout i stderr, tylko z niektórych poleceń w moim skrypcie.
źródło
„Jak” zostało dobrze wyjaśnione w innych odpowiedziach; Chcę odpowiedzieć na pytanie „dlaczego” kod OP nie działa.
Myślą przewodnią jest to, że przekierowania wyjściowe są zaznaczane przed rozwinięciem zmiennej. Przekierowania są faktycznie wykonywane po rozwinięciu zmiennej (dlatego dlaczego można przekierować wyjście do nazwy pliku, która jest przechowywana w zmiennej), ale powłoka identyfikuje przekierowania do późniejszego przetworzenia przed rozwinięciem zmiennych.
Innymi słowy, po rozwinięciu zmiennych jest „za późno” na rozważenie znaku przekierowania (
<
lub>
itp.), Ponieważ powłoka już określiła, które części łańcucha poleceń będą obsługiwać jako przekierowania.Więcej informacji można znaleźć w krokach 1 i 3 wymienionych w:
źródło
Nie jest interpretowany jako „nazwa katalogu”,
>
jest cytowany, więc jest traktowany dosłownie (dokładniej, wysyłasz ciąg>dev/null 2>&1
. Jedynym sposobem na obejście tego jest użycieeval
lub odrodzenie nowej powłoki.Jeśli chodzi o kwestię „pełnego”, o której mowa w pytaniu, po prostu zrób to zamiast tego:
źródło
W twoich zmiennych jest dużo spacji, które nie zostaną właściwie ocenione. Będziesz chciał użyć tego
eval
do skonfigurowania.Umożliwi to podzielenie $ OPT na dwa argumenty (
-p
i-v
) zamiast jednego (-p -v
) i to samo z $ TEST. Zmieniono również użycie,/dev/null
ponieważ jest bardzo mało prawdopodobne, że będziesz miećdev
katalog w bieżącym katalogu.źródło
Odpowiedź enzotib używa dobrej magii deskryptora pliku, ale prostszym rozwiązaniem byłoby po prostu użycie
eval
wiersza (co jednak powoduje dodatkowe obciążenie procesu):źródło