2013-05-23 12 views
14

Mój skrypt bash otrzymuje nazwę pliku (lub względną ścieżkę) jako ciąg, ale musi następnie odczytać z tego pliku. Mogę odczytać tylko z pliku, jeśli zadeklaruję go jako literał bezpośrednio w skrypcie (bez cudzysłowów) ... co jest niemożliwe dla argumentów, ponieważ są one domyślnie ciągami. Przestrzegać:bash: interpretuj zmienną łańcuchową jako nazwę pliku/ścieżkę

a="~/test.txt" 
#Look for it 
if [[ -a $a ]] ; then 
    echo "A Found it" 
else 
    echo "A Error" 
fi 
#Try to use it 
while read line; do 
    echo $line 
done < $a 

b='~/test.txt' 
#Look for it 
if [[ -a $b ]] ; then 
    echo "B Found it" 
else 
    echo "B Error" 
fi 
#Try to use it 
while read line; do 
    echo $line 
done < $b 

c=~/test.txt 
#Look for it 
if [[ -a $c ]] ; then 
    echo "C Found it" 
else 
    echo "C Error" 
fi 
#Try to use it 
while read line; do 
    echo $line 
done < $c 

plonów:

A Error 
./test.sh: line 10: ~/test.txt: No such file or directory 
B Error 
./test: line 12: ~/test.txt: No such file or directory 
C Found it 
Hello 

Jak wspomniano powyżej, nie mogę przekazać argument wiersza polecenia do powyższych procedur, ponieważ mam ten sam problem, że dostać się na cudzysłowami.

+3

"~/test.txt" i "~/test.txt" zatrzymują rozszerzenie ~ w twoim katalogu domowym. ~/test.txt działa, ponieważ jest niecytowany. Przestań używać notacji ~ lub przestań używać cudzysłowów .... –

+1

Jeśli użyjesz argumentu wiersza poleceń skryptu ('$ 1'), wszystko będzie działać poprawnie, ponieważ rozszerzenie katalogu domowego będzie już wykonane przed wywołaniem skryptu. – rici

+0

@rici Tak, pod warunkiem, że '~' nie jest cytowane, gdy jego skrypt jest wywoływany z linii poleceń lub z innego skryptu. To inna historia, gdy jego skrypt jest wywołany z jakiegoś innego programu, który przekazuje _a literał_ '~' To byłby błąd, który powinien zostać naprawiony w innym programie; ale jeśli chce poradzić sobie z taką sytuacją w swoim własnym scenariuszu, prawdopodobnie potrzebuje 'eval'. – Uwe

Odpowiedz

28

Jest to część zasad ~ - ekspansji. W instrukcji obsługi Bash wyraźnie stwierdza się, że to rozszerzenie nie jest wykonywane, gdy cytowany jest ~.

Obejście 1

Nie cytujemy ~.

file=~/path/to/file 

Jeśli chcesz zacytować resztę Nazwa pliku:

file=~/"path with spaces/to/file" 

(Jest to całkowicie legalne w powłoce garden-odmiany.)

Obejście 2

Korzystając $HOME zamiast ~.

file="$HOME/path/to/file" 

BTW: Shell typy zmiennych

Wydaje się być trochę zdezorientowany o typach zmiennych powłoki.

Wszystko jest ciągiem.

Powtarzaj, dopóki nie zapadnie się: Wszystko jest ciągiem. (z wyjątkiem liczb całkowitych, ale są one głównie hacki na szczycie ciągów AFAIK i tablice, ale są tablice ciągów.).

Jest to ciąg shell: "foo". Tak jest "42". Tak jest 42. Tak jest foo. Jeśli nie musisz cytować rzeczy, rozsądnie jest tego nie robić; kto chce wpisać "ls" "-la" "some/dir"?

+0

'file = ~"/ścieżka ze spacjami/do/pliku "' nie działa też. Trzeba napisać ścieżkę 'file = ~/spacjami/do/file" ' – sercxjo

+1

@sercxjo dla mnie działa na zsh i nie działa na bashu. To znaczy. '~ /" 'jest bardziej przenośny. –

+1

Naprawiono @sercxjo (i Nick) – michaelb958

Powiązane problemy