Leerzeichen in Dateinamen und Bash-Skript
Hi Ich bastle mir gerade ein kleines Bash-Skript, welches mir diverse pdf-Dateien zu einem einzigen File zusammen schustert. Nun bin ich in ein Problem gelaufen: Die Dateinamen enthalten Leerzeichen: <--- Begin: Skript ---> #!/bin/bash OUTPUT="home/schuler/Documents/Dossier.pdf " PAGE_01="Eine Datei mit Leerzeichen im Dateinamen.pdf " PAGE_02="Eine weiter Datei mit Leerzeichen im Dateinamen.pdf " PAGE_03="Und so weiter.pdf " ... DOSSIER=$PAGE_01$PAGE_02$PAGE_3 ... pdftk $DOSSIER cat output $OUTPUT <--- End: Skript ---> Irgendwie kommt aber die Bash mit den Leerzeichen in den Variablen $PAGE_* nicht zurecht (oder besser gesagt ich...) Ausserdem gefällt mir das Zusammenhängen der Variablen in der Variablen DOSSIER nicht (da wären Leerzeichen dazwischen schön :-) Hat jemand einen Tip? Vielen Dank! -- Grüsse Marco
Am Dienstag, 18. Januar 2005 16:41 schrieb Marco Schuler:
Hi
Ich bastle mir gerade ein kleines Bash-Skript, welches mir diverse pdf-Dateien zu einem einzigen File zusammen schustert.
Nun bin ich in ein Problem gelaufen: Die Dateinamen enthalten Leerzeichen:
<--- Begin: Skript ---> #!/bin/bash OUTPUT="home/schuler/Documents/Dossier.pdf " PAGE_01="Eine Datei mit Leerzeichen im Dateinamen.pdf " PAGE_02="Eine weiter Datei mit Leerzeichen im Dateinamen.pdf " PAGE_03="Und so weiter.pdf " ... DOSSIER=$PAGE_01$PAGE_02$PAGE_3 ... pdftk $DOSSIER cat output $OUTPUT <--- End: Skript --->
Irgendwie kommt aber die Bash mit den Leerzeichen in den Variablen $PAGE_* nicht zurecht (oder besser gesagt ich...)
Entweder auch die Variablen bei Dossier= quoten... Oder sowas an den Anfang des Skriptes setzen: OIFS="$IFS"; IFS=$'\n' Und ans Ende: IFS="$OIFS"
Ausserdem gefällt mir das Zusammenhängen der Variablen in der Variablen DOSSIER nicht (da wären Leerzeichen dazwischen schön :-)
Evtl escapen, bzw. quoten? DOSSIER="$PAGE_01 $PAGE_02 $PAGE_3" Wäre vielleicht einen Versuch wert... Oder: DOSSIER="'$PAGE_01' '$PAGE_02' '$PAGE_3'" Letzteres ist aber vermutlich quatsch... Bei dem mit IFS=$'\n' bin ich mir aber sicher, dass das hinhaut. Gruß Sören
Am Dienstag, 18. Januar 2005 17:21 schrieb Sören Wengerowsky:
Am Dienstag, 18. Januar 2005 16:41 schrieb Marco Schuler:
<--- Begin: Skript ---> #!/bin/bash OUTPUT="home/schuler/Documents/Dossier.pdf " PAGE_01="Eine Datei mit Leerzeichen im Dateinamen.pdf " PAGE_02="Eine weiter Datei mit Leerzeichen im Dateinamen.pdf " PAGE_03="Und so weiter.pdf " ... DOSSIER=$PAGE_01$PAGE_02$PAGE_3 ... pdftk $DOSSIER cat output $OUTPUT <--- End: Skript --->
Irgendwie kommt aber die Bash mit den Leerzeichen in den Variablen $PAGE_* nicht zurecht (oder besser gesagt ich...)
Entweder auch die Variablen bei Dossier= quoten...
Oder sowas an den Anfang des Skriptes setzen: OIFS="$IFS"; IFS=$'\n'
Und ans Ende: IFS="$OIFS"
Das hat leider nur bedingt geholfen. Zwar wird jetzt der Dateiname als ganzes gesehen, doch pdftk meldet: Error: Failed to open PDF file: Eine Datei mit Leerzeichen im Dateinamen.pdf Error: Failed to open PDF file: Eine weiter Datei mit Leerzeichen im Dateinamen.pdf Error: Failed to open PDF file: Und so weiter.pdf Errors encountered. No output created. Done. Input errors, so no output created.
Ausserdem gefällt mir das Zusammenhängen der Variablen in der Variablen DOSSIER nicht (da wären Leerzeichen dazwischen schön
:-)
Evtl escapen, bzw. quoten?
DOSSIER="$PAGE_01 $PAGE_02 $PAGE_3"
Wäre vielleicht einen Versuch wert...
Oder: DOSSIER="'$PAGE_01' '$PAGE_02' '$PAGE_3'"
Letzteres ist aber vermutlich quatsch...
Da werde ich später noch daran arbeiten. Kosmetik kommt später...
Bei dem mit IFS=$'\n' bin ich mir aber sicher, dass das hinhaut.
Leider nicht so... Sie oben. -- Grüsse Marco
Am Dienstag, 18. Januar 2005 17:47 schrieb Marco Schuler:
Am Dienstag, 18. Januar 2005 17:21 schrieb Sören Wengerowsky: [..]
Oder sowas an den Anfang des Skriptes setzen: OIFS="$IFS"; IFS=$'\n'
Und ans Ende: IFS="$OIFS"
Das hat leider nur bedingt geholfen. Zwar wird jetzt der Dateiname als ganzes gesehen, doch pdftk meldet:
Error: Failed to open PDF file: Eine Datei mit Leerzeichen im Dateinamen.pdf Error: Failed to open PDF file: Eine weiter Datei mit Leerzeichen im Dateinamen.pdf Error: Failed to open PDF file: Und so weiter.pdf Errors encountered. No output created. Done. Input errors, so no output created.
OK. Dann liegt es also nicht am Script, sondern an den Dateinamen? Du könntest vorübergehend alle Dateinamen von Leerzeichen entfernen, und durch ein bestimmtes Zeichen ersetzen, und später wieder rückgängig machen.. Ich habe hier mal was versucht: Mal ein paar Dateien angelegt: soeren@linux:~/test> for i in `seq 1 20`; do touch "tr-test $i";done Nachgeguckt: soeren@linux:~/test> ls tr-test 1 tr-test 10 tr-test 11 tr-test 12 tr-test 13 tr-test 14 tr-test 15 tr-test 16 tr-test 17 tr-test 18 tr-test 19 tr-test 2 tr-test 20 tr-test 3 tr-test 4 tr-test 5 tr-test 6 tr-test 7 tr-test 8 tr-test 9 Das hier kommt an den Anfang des Skriptes (wandelt die Leerzeichen in _ um..) soeren@linux:~/test>for i in tr-test*; do mv "$i" `echo $i | tr ' ' '_'`; done soeren@linux:~/test> ls -1 tr-test_1 tr-test_10 [..] Und das hier kommt ans Ende, und macht das, was das oben gemacht hat, rückwärts... soeren@linux:~/test> for i in tr-test*; do mv "$i" "`echo $i | sed -e 's/_/\ /g'`"; done Und das klappt bei mir auch. soeren@linux:~/test> ls -1 tr-test 1 tr-test 10 tr-test 11 tr-test 12 [..] Wähle eventuell ein anderes Zeichen als _, wenn deine Dateinamen das sowieso schon enthalten... HTH Gruß Sören, auf die Gefahr hin, einen Useless-Award für die komischen Shell-konstruktionen zu bekommen...
Am Dienstag, 18. Januar 2005 21:53 schrieb Sören Wengerowsky:
OK. Dann liegt es also nicht am Script, sondern an den Dateinamen?
Du könntest vorübergehend alle Dateinamen von Leerzeichen entfernen, und durch ein bestimmtes Zeichen ersetzen, und später wieder rückgängig machen..
Tut mir leid, aber es hört sich an wie: "Ich habe ein Loch im Knie und habe damit Probleme, was soll ich machen?" "Mach es zu, und später kannst Du es wieder neu bohren." Mit Leerzeichen in Dateinamen wird man immer wieder Probleme bekommen. Zwar wird überall darauf geachtet, daß auch Dateien mit Leerzeichen im Namen richtig behandelt werden, aber irgendwann hat man immer mal ein schnell dahingeschriebenes Skript dazwischen, das nicht darauf achtet und es kann zu den unglaublichsten Effekten kommen, an die man nie denkt und auch nicht drauf kommt, daß es an einer Datei mit Leerzeichen liegt. Ich kann nur jeden raten, Finger weg von Dateien mit Leerzeichen im Namen. Gilt natürlicht genauso für andere merkwürdige Zeichen, wie <CR> oder <TAB> Bernd
Hallo, Am Mittwoch, 19. Januar 2005 02:31 schrieb Bernd Brodeßer:
Am Dienstag, 18. Januar 2005 21:53 schrieb Sören Wengerowsky:
OK. Dann liegt es also nicht am Script, sondern an den Dateinamen?
Du könntest vorübergehend alle Dateinamen von Leerzeichen entfernen, und durch ein bestimmtes Zeichen ersetzen, und später wieder rückgängig machen..
Tut mir leid, aber es hört sich an wie:
"Ich habe ein Loch im Knie und habe damit Probleme, was soll ich machen?" "Mach es zu, und später kannst Du es wieder neu bohren."
:-D Deine Metaphern sind echt immer gut... Witzig, aber treffend. Ich persönlich habe bei mir auch schon viele Verzeichnisse mit dem Tr-Script bearbeitet. Allerdings weiß ich nicht, ob Marco das vielleicht sonst noch irgendwie braucht, oder es nicht ändern möchte, dass da Leerzeichen sind.. Daher habe ich erstmal die "harmlosere" Variante gepostet. Die beinhaltet natürlich auch das zustopfen des Loches im Knie ;-)
Mit Leerzeichen in Dateinamen wird man immer wieder Probleme bekommen. Zwar wird überall darauf geachtet, daß auch Dateien mit Leerzeichen im Namen richtig behandelt werden, aber irgendwann hat man immer mal ein schnell dahingeschriebenes Skript dazwischen, das nicht darauf achtet und es kann zu den unglaublichsten Effekten kommen, an die man nie denkt und auch nicht drauf kommt, daß es an einer Datei mit Leerzeichen liegt.
ACK Gruß Sören
Am Dienstag, 18. Januar 2005 17:21 schrieb Sören Wengerowsky:
Am Dienstag, 18. Januar 2005 16:41 schrieb Marco Schuler:
<--- Begin: Skript ---> #!/bin/bash OUTPUT="home/schuler/Documents/Dossier.pdf " PAGE_01="Eine Datei mit Leerzeichen im Dateinamen.pdf " PAGE_02="Eine weiter Datei mit Leerzeichen im Dateinamen.pdf " PAGE_03="Und so weiter.pdf " ... DOSSIER=$PAGE_01$PAGE_02$PAGE_3 ... pdftk $DOSSIER cat output $OUTPUT <--- End: Skript --->
Irgendwie kommt aber die Bash mit den Leerzeichen in den Variablen $PAGE_* nicht zurecht (oder besser gesagt ich...)
Entweder auch die Variablen bei Dossier= quoten...
Oder sowas an den Anfang des Skriptes setzen: OIFS="$IFS"; IFS=$'\n'
Und ans Ende: IFS="$OIFS"
Wofür muß man es am Ende wieder zurücksetzen? Wenn das Skript zu Ende ist, ist es zu Ende, da ist es doch egal wie die Variablen eingestellt sind, sie gehen alle verloren. Aber zur eigentlichen Idee: Ja, das geht, aber dann muß man bedenken, daß ab sofort nur noch der Zeilenumbruch als Worttrenner gilt. Das heißt man muß ab jetzt für jedes Wort eine eigene Zeile benutzen, es sei denn, daß die Worte zusammengehören sollen.
Ausserdem gefällt mir das Zusammenhängen der Variablen in der Variablen DOSSIER nicht (da wären Leerzeichen dazwischen schön
:-)
Evtl escapen, bzw. quoten?
DOSSIER="$PAGE_01 $PAGE_02 $PAGE_3"
Wäre vielleicht einen Versuch wert...
Oder: DOSSIER="'$PAGE_01' '$PAGE_02' '$PAGE_3'"
Letzteres ist aber vermutlich quatsch...
Ja, da die einfachen Hochkommata sagen, daß es so genommen werden soll, wie es da steht, also $PAGE_01 und nicht der Inhalt der Variablen PAGE_01 Bernd
Am Dienstag, 18. Januar 2005 21:05 schrieb Bernd Brodeßer:
Am Dienstag, 18. Januar 2005 17:21 schrieb Sören Wengerowsky:
[..]
Und ans Ende: IFS="$OIFS"
Wofür muß man es am Ende wieder zurücksetzen? Wenn das Skript zu Ende ist, ist es zu Ende, da ist es doch egal wie die Variablen eingestellt sind, sie gehen alle verloren.
OK. Ich dachte, das gilt dann für diese Sitzung des Users in dem Xterm oder so.. Aber danke! [..]
DOSSIER="'$PAGE_01' '$PAGE_02' '$PAGE_3'"
Letzteres ist aber vermutlich quatsch...
Ja, da die einfachen Hochkommata sagen, daß es so genommen werden soll, wie es da steht, also $PAGE_01 und nicht der Inhalt der Variablen PAGE_01
Ok. Das dachte ich mir schon. Allerdings war ich mir nicht ganz sicher, was die einfachen Hochkomma eigentlich machen. Diese sind sozusagen die " zweiter Klasse, oder? Gruß Sören
Am Dienstag, 18. Januar 2005 16:41 schrieb Marco Schuler:
Ich bastle mir gerade ein kleines Bash-Skript, welches mir diverse pdf-Dateien zu einem einzigen File zusammen schustert.
Nun bin ich in ein Problem gelaufen: Die Dateinamen enthalten Leerzeichen:
Du kannst Dir eine riesige Latte von Problemen ersparen, wenn Du auf Leerzeichen in Dateinamen Verzichtest. Vermeide es, woimmer es geht.
<--- Begin: Skript ---> #!/bin/bash OUTPUT="home/schuler/Documents/Dossier.pdf " PAGE_01="Eine Datei mit Leerzeichen im Dateinamen.pdf "
In der shellvariablen PAGE_01 steht jetzt Eine Datei mit Leerzeichen im Dateinamen.pdf es ist ein einzelner String der auch Leerzeichen beinhaltet. Das es sich dabei um ein Dateiname handelt ist der Variablen egal.
PAGE_02="Eine weiter Datei mit Leerzeichen im Dateinamen.pdf " PAGE_03="Und so weiter.pdf " ... DOSSIER=$PAGE_01$PAGE_02$PAGE_3 ...
In der shellvariablen DOSSIER steht jetzt Eine Datei mit Leerzeichen im Dateinamen.pdf Eine weiter Datei mit ... Auch das ist ein einzelner String, der Leerzeichen beinhaltet.
pdftk $DOSSIER cat output $OUTPUT
Ich kenne leider den Befehl pdftk nicht, aber das erste Argument, daß Du ihm übergibst lautet: Eine, das zweite Argument lautet: Datei, das dritte: mit, das vierte Leerzeichen usw. irgendwann kommt mal ein Argument, das lautet: weiter.pdf und das nächste schließlich: cat, das vorletzte Argument lautet: output und das letzte schließlich: home/schuler/Documents/Dossier.pdf Das kann keine vernünftige Syntax sein. Es kann eigentlich nur so sein, daß $DOSSIER ein einzelnes Argument sein muß. Um das zu erreichen muß Du im Aufruf $DOSSIER in doppelten Hochkommata setzen, also: pdftk "$DOSSIER" cat output $OUTPUT Dann aber ist Eine Datei mit Leerzeichen im Dateinamen.pdf Eine weiter Datei mit ... ein einzelnes Argument, und pdftk weiß nicht, wo da die Namenstrenner sein sollen. Wie gesagt, ich kenne es nicht, schau daher bitte in den manpages nach, wie die einzelnen Namen getrennt werden müssen.
<--- End: Skript --->
Irgendwie kommt aber die Bash mit den Leerzeichen in den Variablen $PAGE_* nicht zurecht (oder besser gesagt ich...)
Für die bash ist das alles nur eine Ansammlung von Zeichen, die zu interpretieren sind. Du weißt das damit Dateinamen gemeint sind, die bash nicht.
Ausserdem gefällt mir das Zusammenhängen der Variablen in der Variablen DOSSIER nicht (da wären Leerzeichen dazwischen schön :-)
Dann sind die Leerzeichen auch im Inhalt der Variablen DOSSIER mit drin. Außerdem muß Du nach dem = quoten, damit das Leerzeichen nicht als Argumenttrenner gewertet wird. Bernd
Hallo, Am Tue, 18 Jan 2005, Marco Schuler schrieb:
Ich bastle mir gerade ein kleines Bash-Skript, welches mir diverse pdf-Dateien zu einem einzigen File zusammen schustert.
Nun bin ich in ein Problem gelaufen: Die Dateinamen enthalten Leerzeichen:
<--- Begin: Skript ---> #!/bin/bash OUTPUT="home/schuler/Documents/Dossier.pdf " PAGE_01="Eine Datei mit Leerzeichen im Dateinamen.pdf " PAGE_02="Eine weiter Datei mit Leerzeichen im Dateinamen.pdf " PAGE_03="Und so weiter.pdf " ... DOSSIER=$PAGE_01$PAGE_02$PAGE_3 ... pdftk $DOSSIER cat output $OUTPUT <--- End: Skript --->
Irgendwie kommt aber die Bash mit den Leerzeichen in den Variablen $PAGE_* nicht zurecht (oder besser gesagt ich...) Ausserdem gefällt mir das Zusammenhängen der Variablen in der Variablen DOSSIER nicht (da wären Leerzeichen dazwischen schön :-)
Hat jemand einen Tip?
Du hast Glueck, ich hab zufaellig einen tarball von pdftk da und konnte in die manpage schauen, wie pdftk ueberhaupt aufgerufen werden soll... Also: die Leerzeichen am Ende der Variablen PAGE_* solltest du erstmal weglassen, das irritiert nur. So, wie du nun pdftk mit einer zusammengesetzten Variable $DOSSIER aufrufen willst musst du beachten, wie die shell quoted. Lese dazu bitte auch man bash und eine bash-Einfuehrung. Folgendes muesste klappen: ==== UNGETESTET! ==== PAGE_01="Eine ...pdf" PAGE_02="Eine weitere ...pdf" OUTPUT="Ausgabe auch mit Leerzeichen.pdf" DOSSIER="\"${PAGE_01}\" ... \"${PAGE_03}\"" pdftk $DOSSIER cat output "$OUTPUT" ==== Beachte, dass $DOSSIER _nicht_, aber _dass_ $OUTPUT gequoted ist! Warum? In PAGE_xx steht der Dateiname dank der "" bei der Zuweisung _mit_ den Leerzeichen, aber _ohne_ die "". Damit pdftk die einzelnen Dateien erkennt muessen die Eingabedateien als einzelne Argumente uebergeben werden, durch ein Zeichen aus $IFS getrennt. D.h. die einzelnen Dateinamen muessen gequoted sein. Dies wird dadurch erreicht, dass bei der Zuweisung von DOSSIER= doppelt gequoted wird: einmal der gesamte String, und dann jeder Dateiname. Aufgerufen wird dann pdftk "Eine Datei mit Leerzeichen.pdf" "Eine weitere .." cat ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Das komplette Unterstrichene ist der _expandierte_ Inhalt von $DOSSIER. Wuerde man $DOSSIER quoten, so wuerde pdftk nach _einer_ Datei namens '"Eine Datei ..." "Eine weitere ..."' suchen, _inklusive_ der "". Alternativ koenntest du auch pdftk "$PAGE_01" .. "PAGE_03" cat ... aufrufen (hier muessen die einzelnen Variablen wie $OUTPUT gequoted werden!). HTH, -dnh -- # Mmm, yesssss. cookies my preciousssss! Mmm, yes downloads it # is! We mustn't have nasty little gmakeses deleting our # precious cookieses now must we? -- gar.lib.mk of 'konstruct'
participants (4)
-
Bernd Brodeßer
-
David Haller
-
Marco Schuler
-
Sören Wengerowsky