Die gezeigten for
-Schleifen im Artikel funktionieren leider gar nicht. ☺
Noch etwas mehr Kontext: Es geht darum, dass man im Nautilus eine oder mehrere Dateien auswählen kann und dann im Kontextmenü sein Skript aufruft. Das Skript soll dann bestimmte Aktionen auf diesen Dateien durchführen, muss also deren Pfade kennen. Dabei steht man – wie immer – vor dem Problem, dass es sowohl Leerzeichen in Dateinamen als auch sonstige Sonderzeichen geben kann. Um genau zu sein, ist außer Nullbyte und Schrägstrich alles erlaubt (auch bei ext4 noch).
Gestern habe ich hier und hier schon meinen Senf dazugegeben, aber noch ein kleines Detail übersehen. In der Doku zum Nautilus steht, dass Nautilus dem Skript auf mehreren Wegen Informationen über die selektierten Pfade zukommen lässt:
Über Kommandozeilenparameter (für lokale Dateien).
In der Umgebungsvariablen
$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS
(für lokale Dateien).Für Dateien, die beispielsweise über SSH eingebunden sind, dann über die Variable
$NAUTILUS_SCRIPT_SELECTED_URIS
.
Dieses Interface hat aber einen Designfehler: In $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS
werden Zeilenumbrüche als Trenner verwendet, wenn mehrere Dateien selektiert sind. Newlines sind in Dateinamen aber erlaubt. Zugegeben, das wird kaum jemand nutzen, aber wenn das doch mal vorkommt und sei es durch falsch geschriebene eigene Skripte, dann knallt’s. Daher stelle ich die These in den Raum, dass man von dieser Variablen generell die Finger lassen sollte.
Fragt man die selektierten Dateien über die Kommandozeilenparameter ab, dann gibt es dieses Problem nicht, weil hier intern durch C-Strings Nullbytes als Trenner verwendet werden, die in Dateinamen nicht erlaubt sind. Alles ok. Trotzdem gibt es hier am Rande eine Stolperfalle: Nautilus ist hier so freundlich und übergibt nicht den kompletten Pfad an das Skript, sondern nur den Dateinamen. In Ausnahmefällen, wo doch mal der ganze Pfade gebraucht wird, klappt’s also nicht. Muss man wissen.
Insgesamt erscheint mir nun das hier als die „richtige Lösung“ für lokale Dateien:
1 2 3 4 5 6 7 8 9 10 11 12 | #!/bin/bash for i do # Für den Regelfall: echo "[$i]" # Sonderfall, dass ganzer Pfad gebraucht wird: echo "[$PWD/$i]" # ... oder ... echo "[$(readlink -f "$i")]" done |
Die eckigen Klammern nur, damit man sieht, wo Dateinamen anfangen und aufhören.
Ich schreibe da immer die drei Worte „für lokale Dateien“ dazu, weil obiges nicht mehr funktioniert, sobald etwas im Nautilus über’s Netzwerk gemountet wurde, z.B. über SSH. Dann sind Kommandozeilenparameter und $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS
einfach leer. Wie oben schon erwähnt, ist dann zwar $NAUTILUS_SCRIPT_SELECTED_URIS
gesetzt, aber der Name lässt es ja schon vermuten: Da stehen keine Pfade sondern URIs drin. Sprich, für die gängigen Tools, die lokale Dateien bearbeiten, ist das auch wieder unbrauchbar (man könnte also nicht einfach immer $NAUTILUS_SCRIPT_SELECTED_URIS
nutzen, um auf der sicheren Seite zu sein). Und das heißt, man kann keine Skripte schreiben, die transparent in beiden Fällen funktionieren, ohne manuell die Gegebenheiten abzufragen – was hässlich und für einfache Beispiele hier im Wiki zu kompliziert ist, denke ich.
Übrigens ist der Text zur Parameterübergabe missverständlich. Das klingt so, als gäbe es für nicht-lokale Dateien gar keine Möglichkeit mehr, die markierten Dateien abzufragen. Das stimmt aber nicht, nur die Kommandozeilenparameter und $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS
sind leer. Außerdem verstehe ich den Satz bei Punkt 1 dort überhaupt nicht – da fehlt irgendwas.
Ich poste das nun hier, weil ich den Artikel gerne korrigieren würde, aber nicht, ohne vorher noch etwas Feedback und andere Meinungen einzuholen. ☺ Außerdem nutze ich Ubuntu und den Nautilus nur sporadisch, also ist es gut möglich, dass ich irgendwas übersehe.
Nochmal kurz die vorgeschlagenen Änderungen:
Alle
for
-Schleifen wie im obigen Schnipsel (Regelfall).Eventuell ein Hinweis wegen des Sonderfalls, falls ganze Pfade gebraucht werden.
Hinweis, dass das nicht mehr funktioniert, sobald es sich um nicht-lokale Dateien handelt. Vielleicht getrennt ein kleines Beispiel, wie man es dann machen könnte.
Den Text zur Parameterübergabe etwas unmissverständlicher schreiben.