Wie finde ich Leerzeichen im dateinamen

A

aloisius

Jungspund
Hallo,

ich habe ein script mit einer Schleife über alle Dateien in einem Verzeichnis.

#!/bin/sh
for i in `ls *`
do
echo $i
done



Wenn im Verzeichnis Dateien mit Leerzeichen auftauchen z.B. Dateiname = "Datei mit Leerzeichen"
dann liefert das script 3 Zeilen

Datei
mit
Leerzeichen

Ich möchte die Leerzeichen durch ein _ ersetzen. Dazu muss ich aber erstmal prüfen ob eine dateiname Leerzeichen enthält.
Da die Variable $i nie den ganzen Dateinamen mit Leerzeichen enthält kann ich mit $i nicht arbeiten.
Hat jemand eine Idee wie ich das machen kann?
 
Hallo bitmucher,
wenn ich nur eine Datei habe dann kann ich mit name =`find . -type f -name '*\ *' -print `
den dateinamen bekommen.
Wenn ich aber mehrere Dateien mit leerzeichen habe, dann liefert `find ...` auch nur einen stream mit allen Ergebnissen hintereinander. ich kann die einzelnen dateien nicht mehr
unterscheiden.
In einer for schleife bekomme ich dann wieder die Fragmente des dateinamens.
 
Die Dateinamen sind bei find durch Zeilenumbrüche getrennt. Du musst also nur den "Stream" bei den Zeilenumbrüchen splitten und hast die einzelnen Dateinamen.
 
Hi,

das wär dann wohl ein typischer Fall für "while" statt "for":
Code:
ls |       # oder find . -name "* *" -print
while read i; do
    echo "$i"
done
Gruss, A.
 
Hallo,

o.k. mit der while schleife klappt es.
Dann gibt's gleich das nächste Problem. Ich lasse einen Zaehler für die Anzahl der Dateien mitlaufen:
--------------------
#!/bin/sh
zaehler=5
echo "Summe vorher : $zaehler "
ls |
while read i; do
let zaehler=zaehler+1
echo "File Nr. $zaehler , Name: $i "
done

echo "Summe nachher ist : $zaehler "
-----------------
Das script liefert:

Summe vorher : 5
File Nr. 6 , Name: Datei mit Leerzeichen
File Nr. 7 , Name: check.sh
File Nr. 8 , Name: noch eine Datei
Summe nachher ist : 5

was passiert hier ?
 
Hi,

die bash startet für die while-Loop, wenn diese von der Pipe liest, eine Sub-Shell. Der "$zaehler" wird nur in dieser Sub-Shell erhöht, in der Parent-Shell bleibt er unverändert.

Um Werte, die innerhalb der Loop verändert werden, später weiterverwenden zu können, ist mehr Aufwand nötig:

Du könntest versuchen, über exit oder echo die aktualisierten Werte an die Haupt-Shell zurückzuliefern, oder z.B. die Ausgabe von ls in einer Datei zu speichern. Wenn du diese Datei mit einer while-Loop liest, passiert das in der gleichen Shell, neue Werte der Variablen bleiben also nach dem Verlassen der Loop erhalten.

Frage ist natürlich immer, wieviel Aufwand man betreiben will; wenn es nur darum geht, in Dateinamen Leerzeichen durch '_' zu ersetzen, kann man einfach zunächst testen mit z.B.
Code:
find . -name "* *" -print | while read F; do G=$(echo "$F" | tr " " "_"); echo mv "$F" "$G"; done
Wenn das OK aussieht, lässt man einfach das echo for dem mv-Kommando weg ...

A.
 
Das einfachste wird sein, vor der for-Schleife den so genannten "internal field separator" von whitespaces auf ein anderes Zeichen zu setzen, welches nicht in den Dateinamen vorkommt und danach wieder zurück zu setzen:

Code:
#!/bin/sh
OLDIFS=$IFS
IFS=";"
for i in `ls *`
do
echo $i
done
IFS=$OLDIFS
 
Hi,

eventuell ist nicht mal das Umsetzen/Rücksetzen von $IFS nötig: bei mir läuft das ganz einfach so, wenn die Shell selbst die Dateinamen expandiert, statt 'ls' zu bemühen:
Code:
for F in *; do echo "$F"; done
Damit umgeht man auch das Problem, dass 'ls' (ohne die '-d'-Option) bei Verzeichnissen den Inhalt auflistet statt des Dateinamens.

Gruss, A.
 
@ floyd62:
>die bash startet für die while-Loop, wenn diese von der Pipe liest, eine Sub-Shell.
>Der "$zaehler" wird nur in dieser Sub-Shell erhöht, in der Parent-Shell bleibt er unverändert.

der zaehler wert wird doch von der parent shell uebernommen. die while schleife startet mit zaehler=5.
das der veraenderte wert dann nicht zurueckgegeben wird erscheint mir unlogisch.
entweder die variable ist lokal (dann muesste die subshell bei 0 anfangen) oder global.
 
Floyd62 hat Recht. Die Subshell übernimmt $zaehler von der Muttershell, aber nicht umgekehrt. Wie folgt formuliert, klappt es auch mit dem Zähler:
Code:
#!/bin/bash

zaehler=5
echo "Summe vorher : $zaehler "
ls >/tmp/$$.tmp
while read i; do
  ((zaehler++))
  echo "File Nr. $zaehler , Name: $i "
done </tmp/$$.tmp

echo "Summe nachher ist : $zaehler "

rm /tmp/$$.tmp
 
Wenns einfach nur um den count geht und nicht darum die nachher zuzuordnen würde auch ein

find . -type f -name '*\ *' |wc -l

ausreichen.
 

Ähnliche Themen

Skript soll nicht doppelt laufen... kill pkill pid cron

Variable mit 'tr' ändern

Verschlüsseltes Backup-Script mit rsync

find Ausgabe in "Anführungszeichen"

HandbrakeCLI Shell Skript

Zurück
Oben