Vielleicht erklaere ich nochmal etwas genauer wie das hier technisch funktioniert.
Die Shell liest die Eingabezeile, fuehrt ein paar Ersetzungen/Expansions durch, teilt die fertig bearbeitete Zeile dann in Woerter auf und ruft dann den Befehl im ersten Wort mit allen weiteren Woertern als Argumenten auf.
Bei der Eingabezeile
muss die Shell keine Ersetzungen machen. Sie teilt die Zeile in drei Worte:
und ruft dann den Befehl `foo' mit den Argumenten `bar' und `baz' auf.
Nun zum Escaping. Bei der Eingabezeile
muss die Shell wieder keine Ersetzungen machen. Sie teilt die Zeile diesmal, wegen der Quotes, in *zwei* Woerter auf:
und ruft dann den Befehl `foo' mit dem einen Argument `bar baz' auf.
Nun zur Variablenexpansion. Nehmen wir an, die Variable `a' hat den Wert `b c'. Bei der Eingabezeile
macht die Shell zuerst eine Variablenexpansion und ersetzt `$a' durch den Wert `b c'. Damit lautet die Eingabezeile nun
Nun teilt die Shell das in vier Worte auf:
Anschliessend ruft sie den Befehl `foo' mit den drei Argumenten `b', `c' und `blubb' auf.
Nun Expansion mit Escaping/Quoting. Wenn die Variablenexpansion gequotet ist und die Eingabezeile so lautet
dann kommt wieder zuerst die Ersetzung was die Befehlszeile so veraendert:
Dann macht die Shell daraus, wegen der Quotes, nur drei Woerter:
Und ruft dann `foo' mit den zwei Argumenten auf.
Nun noch Singlequotes. Bei der Eingabezeile
macht die Shell keine Variablenexpansion, da sie durch die Singlequotes das Dollarzeichen nicht als Sonderzeichen ansieht, sondern literal verwendet. Die Shell teilt also in drei Worte auf:
und ruft anschliessend den Befehl `foo' mit den zwei Argumenten `$a' und `blubb' auf.
Ihr koennt all diese Faelle durchspielen wenn ihr statt dem Befehl `foo' den Befehl `echo' verwendet, oder noch anschaulicher mit folgender Shellfunktion:
Code: Alles auswählen
foo() { echo "args: $#"; for i in "$@"; do echo "arg: '$i'"; done; }
Nun zu dem Fall mit dem `-i':
Die Befehlszeile ist also
Die Shell muss keine Expansionen machen. Sie teilt in zwei Woerter:
Dann ruft sie den Befehl `rm' mit dem Argument `-i' auf. -- Der Shell ist voellig egal was in den Argumenten steht. Sie interessiert sich nur fuer Expansionen (fuer die das Minuszeichen keine Bedeutung hat) und fuer Worttrennung (wofuer es auch keine Bedeutung hat).
Ebenso im Fall der Eingabezeile
Hier laeuft es exakt identisch ab wie im vorigen Fall, da Singlequotes nur dann einen Unterschied machen, wenn in ihnen Sonderzeichen der Shell oder Whitespace steht -- beides ist hier nicht der Fall. Fuer die Shell ist
ein ebenso normales Wort wie
Beides besteht aus lauter fuer sie uninteressanten Zeichen.
Aus diesem Grund ist es voellig egal wie man `-i' quotet -- das Minus hat fuer die Shell selbst ueberhaupt keine Bedeutung.
Das Minus hat nur fuer Befehle eine Bedeutung, bei denen damit Kommandozeilenoptionen eingeleitet werden. Das ist erst nachdem die Shell fork() und exec() aufgerufen hat und damit die Kontrolle an das aufgerufene Programm uebergeben hat.
Die Loesung liegt also nicht darin, irgendetwas fuer die Shell zu machen (Stichwort: Escaping/Quoting), sondern darin, etwas dagegen zu machen, dass das aufgerufene Programm (hier `rm') das Argument als Option ansieht. Das verhindert man indem man dafuer sorgt, dass das Minuszeichen nicht das erste Zeichen im Argument ist ... indem man eine andere Pfadangabe zur gleichen Datei nutzt.
Ich hoffe, mit dieser Erklaerung ist etwas mehr Verstaendnis und Klarheit in diesen Bereich gekommen. Wenn gewuenscht, kann ich gerne einzelne Aspekte nochmal genauer erklaeren.