Nabend,

nachdem ich jetzt seit dem Nachmittag vergebens rumprobiere, das Internet erfolglos nach Lösungen und Beispielen durchforste und immer noch nicht auf einen grünen Zweig gekommen bin, dachte ich mir, mal hier im Forum eine Anfrage zu starten.

Ich möchte mir ein Bashscript basteln, das in einem beliebigen Verzeichnis alle Unterordner durchsucht und mir alle Dateien vom Typ *.jpg auflistet. Zuerst habe ich es mit dem Befehl ls ohne Erfolg probiert. Entweder es werden alle Dateien angezeigt oder nix. :-(

ls -Rali (in allen möglichen Kombinationen) ~/Musik/*.jpg

Hier ist mal ein Beispiel wie die Ordnerstruktur ausieht
/home/edward/Musik/02_edit/Hubert von Goisern/Derweil 1988-2006 CD1:
01 - Solide Alm.ogg
02 - Heast as nit.ogg
03 - Koa Hiatamadl.ogg
04 - Oben und Unten.ogg
05 - Spinni.ogg
06 - Iawaramoi (Steirer).ogg
07 - Schleiniger.ogg
08 - Goisern.ogg
09 - Weit,weit weg.ogg
10 - Kuahmelcher.ogg
11 - Gott erhalts (unter der Wendung des Zitates- Gott erhalte, Gott beschütze).ogg
12 - Juchitzer.ogg
13 - Panchen Lama.ogg
14 - Kharn-Lu.ogg
15 - Afrika Overtüre.ogg
16 - Abreisejodler.ogg
17 - Akipenda.ogg
Hubert von Goisern - Derweil 1988-2006 CD1.ogg.m3u
Hubert_von_Goisern_Derweil.jpg

/home/edward/Musik/02_edit/Hubert von Goisern/Derweil 1988-2006 CD2:
01 - Da Diab.ogg
02 - Spat.ogg
03 - Fön.ogg
04 - Fia di.ogg
05 - Mercedes Benz.ogg
06 - Da Dasige.ogg
07 - I bi an.ogg
08 - Poika.ogg
09 - Afrika.ogg
10 - Neuer Tag.ogg
11 - Schau, schau.ogg
12 - Diandl woasst nu.ogg
13 - Über d'Alma.ogg
14 - Wann i durchgeh.ogg
15 - Kohler.ogg
16 - Schönberger.ogg
17 - Da Insrige.ogg
Hubert von Goisern - Derweil 1988-2006 CD2.ogg.m3u
Hubert_von_Goisern_Derweil.jpg
Dann habe ich den Befehl find ausprobiert.

In der Konsole funktionierts (im Bashscript nicht)
find ~/Musik/02_edit/ -iname *.jpg
/home/edward/Musik/02_edit/Hubert von Goisern/Derweil 1988-2006 CD2/Hubert_von_Goisern_Derweil.jpg
/home/edward/Musik/02_edit/Hubert von Goisern/Derweil 1988-2006 CD1/Hubert_von_Goisern_Derweil.jpg
Das Bashscript
#!/bin/bash

for myDatei in $(find ~/Musik/02_edit/ -iname *.jpg)
do
	BaseName=$(basename "$myDatei")
	DirName=$(dirname "$myDatei")

	echo "DateiName	= $myDatei"
	echo "BaseName	= $BaseName"
	echo "DirName	= $DirName"	
done
Scriptausgabe
DateiName	= /home/edward/Musik/02_edit/Hubert
BaseName	= Hubert
DirName	= /home/edward/Musik/02_edit
DateiName	= von
BaseName	= von
DirName	= .
DateiName	= Goisern/Derweil
BaseName	= Derweil
DirName	= Goisern
DateiName	= 1988-2006
BaseName	= 1988-2006
DirName	= .
DateiName	= CD2/Hubert_von_Goisern_Derweil.jpg
BaseName	= Hubert_von_Goisern_Derweil.jpg
DirName	= CD2
DateiName	= /home/edward/Musik/02_edit/Hubert
BaseName	= Hubert
DirName	= /home/edward/Musik/02_edit
DateiName	= von
BaseName	= von
DirName	= .
DateiName	= Goisern/Derweil
BaseName	= Derweil
DirName	= Goisern
DateiName	= 1988-2006
BaseName	= 1988-2006
DirName	= .
DateiName	= CD1/Hubert_von_Goisern_Derweil.jpg
BaseName	= Hubert_von_Goisern_Derweil.jpg
DirName	= CD1
Wo muß ich dran drehen, damit ich eine vernünftige Ausgabe (auch von Dateien und Ordner mit Leerzeichen drin) bekomme?

Beste Grüße,

Edward
Du hast quotes vergessen:
for myDatei in "$(find ~/Musik/02_edit/ -iname *.jpg)"
portix schriebDu hast quotes vergessen:
Ja, Quoting ist sein Problem, aber so wird er es nicht los. 😉

Benutzt du `*.jpg` ohne Quotes, dann wird das von der aufrufenden Shell expandiert und nicht von `find`. Bei der Befehlssubstitution `$(...)` wird über die einzelnen Worte der Ausgabe des Befehls iteriert, was du nicht willst. Dein Schleifenrumpf hingegen ist völlig richtig. 🙂

Zwei Möglichkeiten:
#!/bin/bash

while read -rd "" myDatei
do
	BaseName=$(basename "$myDatei")
	DirName=$(dirname "$myDatei")

	echo "DateiName	= $myDatei"
	echo "BaseName	= $BaseName"
	echo "DirName	= $DirName"	
done < <(find ~/Musik/02_edit/ -iname "*.jpg" -print0)
Das wäre die korrekte Variante, da zum Trennen der Dateinamen Bytes mit dem Wert Null verwendet werden. Null-Bytes sind neben dem einzelnen Slash die einzigen Zeichen, die nicht in Dateinamen erlaubt sind (bei ext*). Die Prozesssubstitution statt einer direkten Pipe (`find ... | while read ...`) würdest du nur brauchen, falls du innerhalb der Schleife Variablen setzt, die du nach der Schleife weiterverwenden willst. Durch eine Pipe würde die Schleife nämlich in einer Subshell laufen. Ich schreibe das in der Regel direkt so hin, weil man früher oder später eben doch ein Ergebnis der Schleife weiterverarbeiten möchte.

Aber, wenn du schon die Bash nutzt (wobei die Prozesssubstitution auch schon ein Bashism ist), dann geht’s auch etwas schöner:
#!/bin/bash

shopt -s globstar nocaseglob
for myDatei in ~/Musik/02_edit/**/*.jpg
do
    # ...
done
Danke,

ich habs korrigiert.
#!/bin/bash

for myDatei in "$(find ~/Musik/02_edit/ -iname *.jpg)"
do
	echo "$myDatei"
done
und die Ausgabe ist ok.
/home/edward/Musik/02_edit/Hubert von Goisern/Derweil 1988-2006 CD2/Hubert_von_Goisern_Derweil.jpg
/home/edward/Musik/02_edit/Hubert von Goisern/Derweil 1988-2006 CD1/Hubert_von_Goisern_Derweil.jpg
So, jetzt habe ich mal die Ausgabe etwas formatiert.
Warum ist jetzt die Ausgabe falsch?
#!/bin/bash

for myDatei in "$(find ~/Musik/02_edit/ -iname *.jpg)"
do
	echo "DateiName = $myDatei"
done
Da fehlt doch ein "Dateiname = " oder?
DateiName	= /home/edward/Musik/02_edit/Hubert von Goisern/Derweil 1988-2006 CD2/Hubert_von_Goisern_Derweil.jpg
/home/edward/Musik/02_edit/Hubert von Goisern/Derweil 1988-2006 CD1/Hubert_von_Goisern_Derweil.jpg
Jetzt habe ich die Ausgabe um BaseName erweitert. Warum wird die Ausgabe nur einmal gemacht und nicht wie erwartet, zweimal?
#!/bin/bash

for myDatei in "$(find ~/Musik/02_edit/ -iname *.jpg)"
do
	BaseName=$(basename "$myDatei")
	echo "$BaseName"
done
Die Ausgabe müßte eigentlich für jeden Ordner einmal kommen:
Hubert_von_Goisern_Derweil.jpg

Ein weiterer Knackpunkt. Ich habe die Ausgabe auf DirName geändert. Leider ist auch diese Ausgabe fehlerhaft. Warum?
#!/bin/bash

for myDatei in "$(find ~/Musik/02_edit/ -iname *.jpg)"
do
	DirName=$(dirname "$myDatei")
	echo "$DirName"
done

/home/edward/Musik/02_edit/Hubert von Goisern/Derweil 1988-2006 CD2/Hubert_von_Goisern_Derweil.jpg
/home/edward/Musik/02_edit/Hubert von Goisern/Derweil 1988-2006 CD1
Beste Grüße,

Edward
portix’ Vorschlag war ein bisschen fehlleitend. Deine Schleife iteriert jetzt über ein einziges Element, das alle Dateinamen durch Newlines getrennt enthält. Die Ergebnisse sind dann folgerichtig.
@Vain,
@portix,

herzlichen Dank für Eure Unterstützung. Ich habe nun Vains Variante genutzt; sie macht genau das, was ich erwarte. Darauf aufbauend werde ich mein Script nun um einige Funktionen erweitern.

Beste Grüße,

Edward
So, das hier ist mein vollständiger Code.
#!/bin/bash

#Pfad="~/Musik/02_edit/"
ZielName="folder.jpg"

while read -rd "" myDatei
do
	BaseName=$(basename "$myDatei")
	DirName="$(dirname "$myDatei")"

	echo "DateiName	= $myDatei"
	echo "DirName		= $DirName"
	echo "BaseName	= $BaseName"
	
	if [ "$BaseName" != "$ZielName" ]; then
		echo "ZielName	= $DirName/$ZielName"
		cp "$myDatei" "$DirName/$ZielName"
	fi
	echo
	
done < <(find ~/Musik/02_edit/ -iname "*.jpg" -print0)
Warum habe ich das gemacht? Nun, ich besitze einen Sansa Fuze V2 MP3-Player. Meine Musik (hauptsächlich *.ogg und wenige *.mp3) ist ordentlich vertaggt und mit "Cover Art" versehen, sowohl in den Tags als auch im Ordner. Leider ist die original Sansa-Firmware nicht in der Lage, die "Cover Art" sauber darzustellen. So bin ich zu Rockbox gekommen. Scheinbar erwartet Rockbox die "Cover Art" als folder.jpg, so das ich meine Bilder umkopieren bzw. umbennen muß. Dafür ist das obige Script gedacht.

Ciao,

Edward