2013-05-23 15 views
14

Mein Bash-Skript erhält einen Dateinamen (oder relativen Pfad) als String, muss aber dann aus dieser Datei lesen. Ich kann nur von einem Dateinamen lesen, wenn ich es direkt im Skript (ohne Anführungszeichen) als Literal deklariere ... was für Argumente unmöglich ist, da sie implizit mit Strings beginnen. Beachten Sie:Bash: Interpretiere String-Variable als Dateiname/Pfad

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 

RENDITEN:

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 

Wie oben erwähnt, ich keine Befehlszeilenargument zu den Routinen oben, da ich das gleiche Verhalten, das ich auf den Strings in Anführungszeichen bekommen passieren kann.

+3

"~/test.txt" und "~/test.txt" stoppen die Erweiterung von ~ in Ihr Home-Verzeichnis. ~/test.txt funktioniert, weil es nicht in Anführungszeichen steht. Stoppen Sie die Verwendung der ~-Notation oder stoppen Sie die Verwendung von Anführungszeichen .... –

+1

Wenn Sie nur das Befehlszeilenargument ('$ 1') des Skripts verwenden, wird alles funktionieren, da die Home-Verzeichniserweiterung bereits ausgeführt wurde, bevor das Skript aufgerufen wird. – rici

+0

@rici Ja, vorausgesetzt, dass '' 'nicht zitiert wird, wenn sein Skript von der Befehlszeile oder von einem anderen Skript aufgerufen wird. Es ist eine andere Geschichte, wenn sein Skript von einem anderen Programm aufgerufen wird, das _a literal_ '~' übergibt. Das wäre ein Fehler, der in dem anderen Programm behoben werden sollte; Aber wenn er sich in seinem eigenen Drehbuch mit einem solchen Fall befassen will, braucht er wahrscheinlich 'eval'. – Uwe

Antwort

28

Dies ist Teil der Regeln von ~ -Expansion. Im Bash-Handbuch wird klar angegeben, dass diese Erweiterung nicht ausgeführt wird, wenn ~ angegeben wird.

Behelfslösung 1

Sie die ~ nicht zitieren.

file=~/path/to/file 

Wenn Sie den Rest des Dateinamens zu zitieren:

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

(Dies in einem Garten-Sorte Shell vollkommen legal ist.)

Problemumgehung 2

Verwenden $HOME anstelle von ~.

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

BTW: Shell-Variablen-Typen

Sie scheinen ein wenig verwirrt über die Arten von Shell-Variablen zu sein.

Alles ist eine Zeichenfolge.

Wiederholen Sie, bis es sinkt: Alles ist eine Zeichenfolge. (ausgenommen ganze Zahlen, aber sie sind Hacks meist auf den Saiten AFAIK und Arrays, aber sie sind Arrays von Strings..)

Dies ist ein Shell-string: "foo". So ist "42". So ist 42. So ist foo. Wenn Sie keine Dinge zitieren müssen, ist es vernünftig, nicht; Wer möchte "ls" "-la" "some/dir" eingeben?

+0

'file = ~"/Pfad mit Leerzeichen/zu/Datei "' funktioniert auch nicht. Es ist notwendig, 'file = ~ /" Pfad mit Leerzeichen/zu/Datei "' – sercxjo

+1

@sercxjo für mich zu schreiben es funktioniert auf zsh und funktioniert nicht auf bash. I.e. '~ /" 'ist tragbarer. –

+1

@sercxjo (und Nick) behoben – michaelb958

Verwandte Themen