Shellscript-Problem mit Leerzeichen im Dateinamen
Dateien verschieben mit FOR-Schleife
Hallo miteinander,
ich habe mir ein kleines Shellscript geschrieben das über einen cronjob regelmäßig gestartet wird. Es soll mir lediglich Dateien, wenn vorhanden, in ein anderes Verzeichnis schieben.
#!/bin/sh
for FILE in `ls -1 /home/comeIn`
#(Alternative1): for FILE in `ls -1 --quoting-style=shell /home/comeIn`
#(Alternative2): for FILE in $(ls -1 /home/comeIn)
do
echo "/home/comeIn: verschiebe" $FILE "--> /home/me/incoming"
mv /home/comeIn/$FILE /home/me/incoming/$FILE
done
Die Ausgabe des Scripts wird mir dann als Mail zugeschickt (macht der cronjob automatisch).
Theoretisch bräuchte ich diese Schleife nicht, allerdings werden mir dann immer Fehlermeldungen per Mail geschickt, die mir andauernd erzählen dass da keine Datei ist. Der Sinn der Sache ist aber der umgekehrte, ich möchte nur Mails bekommen wenn Dateien da und verschoben sind!
Soviel zur Aufgabenstellung. Das eigentliche PROBLEM an der Sache ist, dass das Script über Dateien stolpert die Leerzeichen im Dateinamen haben. Die einzelnen Textteile der Dateinamen werden als einzelne Dateien behandelt und ich werde mit Fehlermeldungen bombardiert. Übrigens schaffen auch die angegebenen Alternativen das gleiche Ergebnis.
Wie verklickere ich der FOR-Schleife, dass der Inhalt FILE-Variable die komplette Zeile der ls-Ausgabe sein soll???
Oder gibt es noch komplett andere Ansätze dafür?
Vielleicht kann mir da jemand helfen... Vielen Dank - Tobias
Hallo miteinander,
ich habe mir ein kleines Shellscript geschrieben das über einen cronjob regelmäßig gestartet wird. Es soll mir lediglich Dateien, wenn vorhanden, in ein anderes Verzeichnis schieben.
#!/bin/sh
for FILE in `ls -1 /home/comeIn`
#(Alternative1): for FILE in `ls -1 --quoting-style=shell /home/comeIn`
#(Alternative2): for FILE in $(ls -1 /home/comeIn)
do
echo "/home/comeIn: verschiebe" $FILE "--> /home/me/incoming"
mv /home/comeIn/$FILE /home/me/incoming/$FILE
done
Die Ausgabe des Scripts wird mir dann als Mail zugeschickt (macht der cronjob automatisch).
Theoretisch bräuchte ich diese Schleife nicht, allerdings werden mir dann immer Fehlermeldungen per Mail geschickt, die mir andauernd erzählen dass da keine Datei ist. Der Sinn der Sache ist aber der umgekehrte, ich möchte nur Mails bekommen wenn Dateien da und verschoben sind!
Soviel zur Aufgabenstellung. Das eigentliche PROBLEM an der Sache ist, dass das Script über Dateien stolpert die Leerzeichen im Dateinamen haben. Die einzelnen Textteile der Dateinamen werden als einzelne Dateien behandelt und ich werde mit Fehlermeldungen bombardiert. Übrigens schaffen auch die angegebenen Alternativen das gleiche Ergebnis.
Wie verklickere ich der FOR-Schleife, dass der Inhalt FILE-Variable die komplette Zeile der ls-Ausgabe sein soll???
Oder gibt es noch komplett andere Ansätze dafür?
Vielleicht kann mir da jemand helfen... Vielen Dank - Tobias
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 72072
Url: https://administrator.de/contentid/72072
Ausgedruckt am: 22.11.2024 um 05:11 Uhr
9 Kommentare
Neuester Kommentar
Moin KHP,
das sollte in der bash genauso funktionieren wie unter M$'s CMD-Shell: den kompletten Pfad incl. $FILE in Anführungszeichen einschließen.
Anmerkung: statt "-quoting-style" kannst Du auch einfach "-b" schreiben.
Alternativ kannst Du natürlich die Leerzeichen im Namen "maskieren", d.h. jedes Leerzeichen durch die Sequenz Backslash-Leerzeichen ersetzen.
Nötig ist das nicht, aber wenn Du grad am Skripten-Üben bist...
Grüße
Biber
das sollte in der bash genauso funktionieren wie unter M$'s CMD-Shell: den kompletten Pfad incl. $FILE in Anführungszeichen einschließen.
mv "/home/comeIn/$FILE" "home/me/incoming/$FILE"
Anmerkung: statt "-quoting-style" kannst Du auch einfach "-b" schreiben.
Alternativ kannst Du natürlich die Leerzeichen im Namen "maskieren", d.h. jedes Leerzeichen durch die Sequenz Backslash-Leerzeichen ersetzen.
sed -e 's/\ /\\\ /g'
Grüße
Biber
Moin KHP,
sorry, ich hab jetzt grad kein richtiges OS hier zum Testen.
Dennoch, eigentlich sollte es so funktionieren:
Die zweite Frage - sed und regular expressions lassen wir erstmal noch links liegen.
Nur kurz: Ziel soll ja sein, in dem String "Dateiname mit Leerzeichen.bla" alle Leerzeichen zu "maskieren", d.h. der Shell mitzuteilen, dass dieses Leerzeichen halt "einfach nur Buchstabe" ist, auch wenn er sonst anders interpetiert werden würde. Z.B. als Wortende.
...bedeutet also nur: Ersetze alle Zeichen "Leerzeichen" ( ="/\ ") durch "Backslash-Leerzeichen".
Und in diesem Ersatz-String ist nun auch ausgerechnet ein spezielles Zeichen (Backslash), das selbst maskiert werden muss-
Daher sieht der Ersatzstring etwas strange aus: "/\\\ " . Heißt aber nur: Ersetze mit "einem Backslash und einem Leerzeichen".
Näheres dazu bei "man sed" oder "man regular expression".
Gruss
Biber
sorry, ich hab jetzt grad kein richtiges OS hier zum Testen.
Dennoch, eigentlich sollte es so funktionieren:
#!/bin/sh
for FILE in `ls -b /home/comeIn`
do
echo "/home/comeIn: verschiebe" $FILE "--> /home/me/incoming"
mv "/home/comeIn/$FILE" "/home/me/incoming/$FILE"
done
Die zweite Frage - sed und regular expressions lassen wir erstmal noch links liegen.
Nur kurz: Ziel soll ja sein, in dem String "Dateiname mit Leerzeichen.bla" alle Leerzeichen zu "maskieren", d.h. der Shell mitzuteilen, dass dieses Leerzeichen halt "einfach nur Buchstabe" ist, auch wenn er sonst anders interpetiert werden würde. Z.B. als Wortende.
sed -e 's/\ /\\\ /g'
Und in diesem Ersatz-String ist nun auch ausgerechnet ein spezielles Zeichen (Backslash), das selbst maskiert werden muss-
Daher sieht der Ersatzstring etwas strange aus: "/\\\ " . Heißt aber nur: Ersetze mit "einem Backslash und einem Leerzeichen".
Näheres dazu bei "man sed" oder "man regular expression".
Gruss
Biber
Hallo,
das Problem ist, dass die for-Schleife schon nur die "zerstückelten" Namen zu Gesicht bekommt.
Eine Lösung wäre statt einer for-Schleife eine while-Schleife zu benutzen.
ls -1 /home/comeIn | while read FILE do
mv -f /home/comeIn/"$FILE" /home/me/incomming/
done
Cheers!
#!/bin/sh
for FILE in `ls -1 /home/comeIn`
#(Alternative1): for FILE in `ls -1
--quoting-style=shell /home/comeIn`
#(Alternative2): for FILE in $(ls -1
/home/comeIn)
do
echo "/home/comeIn: verschiebe"
$FILE "--> /home/me/incoming"
mv /home/comeIn/$FILE
/home/me/incoming/$FILE
done
for FILE in `ls -1 /home/comeIn`
#(Alternative1): for FILE in `ls -1
--quoting-style=shell /home/comeIn`
#(Alternative2): for FILE in $(ls -1
/home/comeIn)
do
echo "/home/comeIn: verschiebe"
$FILE "--> /home/me/incoming"
mv /home/comeIn/$FILE
/home/me/incoming/$FILE
done
das Problem ist, dass die for-Schleife schon nur die "zerstückelten" Namen zu Gesicht bekommt.
Eine Lösung wäre statt einer for-Schleife eine while-Schleife zu benutzen.
ls -1 /home/comeIn | while read FILE do
mv -f /home/comeIn/"$FILE" /home/me/incomming/
done
Cheers!
versucht doch mal:
das fängt leerzeichen im pfad und dateinamen ab. außerdem braucht man für ne for kein ls, kost nur performance.
die while mag funzen, hat aber den nachteil, dass man wieder n ls machen muss und außerdem öffnet man durch die pipe ne subshell. d.h. beschreibst du in der while ne variable, ist die außerhalb nicht mehr verfügbar.
winky@T61:~$ ./script.sh BLAN\ K/
BLAN K//foo bar
-rw-r--r-- 1 winky winky 0 2010-01-14 18:44 BLAN K//foo bar
BLAN K//foo_bar
-rw-r--r-- 1 winky winky 0 2010-01-14 19:00 BLAN K//foo_bar
winky@T61:~$ cat script.sh
#!/bin/bash
PFAD="$1"
for FILE in "$PFAD"/*
do
echo "$FILE"
ls -l "$FILE"
done
das fängt leerzeichen im pfad und dateinamen ab. außerdem braucht man für ne for kein ls, kost nur performance.
die while mag funzen, hat aber den nachteil, dass man wieder n ls machen muss und außerdem öffnet man durch die pipe ne subshell. d.h. beschreibst du in der while ne variable, ist die außerhalb nicht mehr verfügbar.
while ist nicht die schnellste möglichkeit, aber die sicherere! bei der for schleife gibt es probleme wenn zu viele dateien vorhanden sind. wenn "$PFAD"/* zu mehr als 32K zeichen expandiert werden soll gibt es eine fehlermedlung und nichts passiert. diese einschränkung wird bei den for schleifen nie erwähnt.
Hier mal mein praktisches Beispiel, bei dem ich eine Auflistung von tif-Dateien in der KornShell von einem Windows-Netzwerkpfad in ein Arbeitsverzeichnis kopieren will:
#!/bin/sh
#Windows-Pfad zum Share auf dem Fileserver
DTAUSPATH='//fsnt-01-nl/ver_r$/11 SKS/27 IDEAL Antraege/Eingang_TEST'
DATEIART=*.tif
DATPATH=D:\Batch\IDEAL
do
echo DATEI: "$DATEI"
cp -fv "$DATEI" $DATPATH
done
Und siehe da, die Leerzeichen sind im Netzwerkpfad kein Problem mehr.
#!/bin/sh
#Windows-Pfad zum Share auf dem Fileserver
DTAUSPATH='//fsnt-01-nl/ver_r$/11 SKS/27 IDEAL Antraege/Eingang_TEST'
DATEIART=*.tif
DATPATH=D:\Batch\IDEAL
- wie oben bereits gesehen:
do
echo DATEI: "$DATEI"
cp -fv "$DATEI" $DATPATH
done
Und siehe da, die Leerzeichen sind im Netzwerkpfad kein Problem mehr.