~
in Anführungszeichen bleibt wörtlich ~
. Der relevante Teil des Bash-Referenzhandbuchs beginnt mit
Wenn ein Wort mit einem nicht zitierten Tilde-Zeichen (
~
) beginnt ,…
Um den Unterschied zu sehen, vergleichen Sie:
file="~/.gitconfig" echo "$file" file=~/".gitconfig" echo "$file"
In Ihrem ersten Beispiel $(…)
arbeitet zuerst und ist in seinem Kontext ~
nicht in Anführungszeichen gesetzt. So wird es wie erwartet erweitert.
Ihr $file
, wenn es "nicht funktioniert" enthält wörtlich ~
. POSIX-Standard sagt :
Die Reihenfolge der Worterweiterung lautet wie folgt:
Die Tilde-Erweiterung […], die Parametererweiterung […], die Befehlsersetzung […] und die arithmetische Erweiterung […] werden von Anfang bis Ende durchgeführt. […]
Da eine Tilde-Erweiterung vor der Parametererweiterung ausgeführt wird, wird eine Variable, deren Erweiterung erweitert wird, ~/something
nicht weiter auf einen geeigneten Pfad erweitert.
Denken Sie daran, ~
oder ~/
ist das Besondere an Ihrer Shell unter Umständen aber zu (fast?) Alle anderen Werkzeug, es ist kein gültiger Pfad. Wenn es funktioniert, liegt es daran, dass die Shell zuerst ihre "Magie" ausführt und das andere Werkzeug den bereits erweiterten Pfad (wie /Users/jord
) sieht .
Beachten Sie, dass die Tilde-Erweiterung in Ihrem letzten Beispiel nicht funktioniert. Sie erhalten immer noch das Literal ~
und es ist zu spät, um ohne zusätzliche Tricks (wie eval
) der Shell etwas dagegen tun zu können . dirname
beschwert sich nicht, weil es mit strings funktioniert. Es ist egal, ob der angegebene Pfad gültig ist, existiert usw. Er sucht im Grunde nur nach der letzten Komponente ohne Schrägstrich und verwirft sie mit nachstehenden Schrägstrichen (falls vorhanden).
Siehe auch diese Antwort .