Zuerst werde ich das Problem beschreiben. Ich kopiere oft Dateien von meinem Linux-Desktop auf mein Android-Tablet. Aus Gründen, auf die ich lieber nicht eingehen möchte, ist dies am einfachsten, wenn ich sshDroid (einen SSH-Server) auf meinem Tablet ausgeführt und scp
von der Shell aus verwendet habe, um Dateien zu kopieren. Der scp
Befehl hat die folgende Form:Escaping-Parameter zu Bash-Funktion
scp -P 2222 ./some\ document\:\ with\ subtitle\ -\ author.txt \
[email protected]:/sdcard/uploads
Das einzige, was in diesem Ausdruck ändert, ist der Name der Datei, und das ist ganz leicht über Tab-Vervollständigung erreicht. Nicht einmal die IP-Adresse ändert sich. Da ich Dateien oft hochlade, möchte ich nicht immer wieder dieselben Zeichen eingeben. Zu diesem Zweck dachte ich, ich würde eine Shell-Funktion schreiben und an .bashrc
anhängen. Die Funktion I ist geschrieben wie folgt:
upload(){ scp -P 2222 [email protected] [email protected]:/sdcard/uploads; }
es Nutzung sein soll:
upload ./some\ document\:\ with\ subtitle\ -\ author.txt
aber wenn ich es versuche ich erhalten die folgende Ausgabe:
SSHDroid
Use 'root' as username
Default password is 'admin'
[email protected]'s password:
./some: No such file or directory
ssh: Could not resolve hostname document: Name or service not known
with: No such file or directory
subtitle: No such file or directory
-: No such file or directory
author.txt: No such file or directory
Es sieht aus wie bash entfernt automatisch den Dateinamen, bevor er ihn an die Funktion übergibt, und der Befehl scp behandelt ihn aufgrund der Leerzeichen im Namen als mehrere Dateinamen.
Meine Frage ist: Wie behalte ich die Backslashes in den Parameter, oder wie kann ich es innerhalb der Funktion wiederherstellen? Nachdem ich eine Weile damit herumgespielt habe, bin ich sehr versucht, ein einfaches Python-Skript zu schreiben und es in/usr/local/bin ablegen. Gibt es eine andere bash-native Lösung, die ich vermisse?
Es ist nicht "URL-Kodierung" das ist das Problem, dann ist es String-Splitting. Unescaping passiert immer früh im Parsing-Prozess, aber es soll - das ist ein Feature, kein Bug. Das Problem besteht darin, dass Ihr nicht entesterter Inhalt dann string-split oder glob expandiert wird, weil er nicht korrekt zitiert wurde. Siehe http://mywiki.wooledge.org/BashParser –
BTW, wenn Ihr Ziel ist, ein gutes Verständnis des Ausführungsmodell zu haben [und die BashParser-Seite lässt Sie immer noch weniger als zuversichtlich], berührt BashFAQ # 50 die gleichen Themen, die einige der Missverständnisse hinter dieser Frage zu begründen; siehe http://mywiki.wooledge.org/BashFAQ/050 –