Antoras schriebWirklich verstanden hab ich die Erklärung jetzt nicht. Ich werde mir einfach merken, dass wenn ich ein einzelnes Argument übergeben möchte, dann muss die Variable in Anführungsstriche stehen.
Oh ja dieses "Problem" hat mich in meinen Anfängen, des Bash-scripting auch fast in den Wahnsinn getrieben. Ich versuche einmal so gut wie möglich aufzuschlüsseln, was da genau passiert:
Du kannst dir Bash-variablen nahezu als Text-Makros vorstellen (einigen Bash-veteranen wird es dabei wahrscheinlich eiskalt den Rücken runterlaufen, aber ich glaube, damit ist es am einfachsten verständlich). Sprich wenn eine Zeichenkette der Form $... in doppelten Anführungszeichen oder in "freier Wildbahn" auftritt, wird nachgesehn ob dafür eine "Ersetzung" existiert bzw. generiert werden kann. Falls ja wird die Zeichenkette durch selbige ersetzt andernfalls durch eine leere Zeichenkette. Die einfachen Anführungszeichen stellen hierbei eine Ausnahme dar: Sie verhindern jegliche Ersetzung.
So viel zur Grundlage (Versteh das nicht falsch, ich will dich nicht für dumm verkaufen, nur auf Nummer sicher gehn. Falls du das schon weißt, ignorier es 🙂 ). Das Problem bei deinem Skript ist nun, dass eben diese Interpretation nur
einmal vorgenommen wird. Folglich expandiert folgendes:
var=hallo
var2='$var'
echo $var2
nicht etwa zu
hallo sondern zu
$var. Und in Deinem Skript expandiert
$name zu
'a b (c).txt'. Da jetzt also schon eine Interpretation stattgefunden hat, werden die expandierten einfachen Anführungszeichen nicht mehr weiter interpretiert, sondern einfach als ganz normale Zeichen aufgefasst, die so wie sie sind an das aufgerufene Programm weitergereicht werden (in dem Fall mkdir).
Für den Effekt, den du erziehlen willst, müsste die Bash die Expansion von
$name also ein zweites mal interpretieren. Sowas ist auch durchaus möglich. Und zwar mit dem Shell-Builtin
eval. Um deinen Code so funktionieren zu lassen, wie du willst (blastmasters Version ist da natürlich die gängige und viel bessere. Das hier ist nur zum Verständnis), müsste deine Skript praktisch folgendermaßen aussehen:
name="'a b (c).txt'"
eval mkdir $name
Damit wird erst
$name zu
'a b (c).txt' ersetzt und dann wiederrum, bekommt die Bash genau die Zeichenkette:
mkdir 'a b (c).txt'
vor Gesicht und macht genau das, was du von ihr erwartest :-).
Ich hoffe das war jetzt alles so einigermaßen verständlich :-P.
Gruß Domi