BASH: Alle Verzeichnisse in einem Verzeichnis finden, auch mit Leerzeichen

Post Reply
Message
Author
domseichter
Posts: 57
Joined: 11. Feb 2002 22:08
Location: Laufen
Contact:

BASH: Alle Verzeichnisse in einem Verzeichnis finden, auch mit Leerzeichen

#1 Post by domseichter »

Hallo,

Ich habe folgendes Problem in einem bash script. Ich muss in einem for loop alle Verzeichnisse im Aktuellen Verzeichnis (inklusive derer Unterverzeichnisse) durchgehen. Ich möchte das in $i immer ein Verzeichnis wieder findet. Beim ersten durchlauf /home/dir1, beim 2. durchlauf /home/dir2 und dann /home/dir2/subdir1 usw. . Das ganze klappt auch ganz gut, solange die Verzeichnisnamen keine Leerzeichen enthalten. Ich habe es schon mit Anführungszeichen an verschiedenen stellen probiert, aber ohne Erfolg (den kompletten find Befehl in Anführungszeichen oder $i bein echo Befehl).

<blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">
for i in $(find $PWD -type d | sort );
do
echo $i # in wirklich wird mit i jetzt etwas sinnvolles gemacht <img src="http://www.pl-forum.de/UltraBoard/Images/Wilk.gif" border="0" align="middle">
done;
</font><hr></pre></blockquote>

Ich hoffe ihr habt eine Idee und könnt mir weiterhelfen.

CU Dom
<!--http--><a href="http://www.kbarcode.net" target="_blank">kbarcode.net</a><!--url--> - <!--http--><a href="http://www.krename.net" target="_blank">krename.net</a><!--url-->

Jochen

Re: BASH: Alle Verzeichnisse in einem Verzeichnis finden, auch mit Leerzeichen

#2 Post by Jochen »

Hi!

Dein Problem liegt darin, dass die Shell zuerst die Liste der Verzeichnisse aufbaut, sie für die for-Schleife einsetzt und <i>dann</i> die Liste anhand der Blanks in einzelne Elemente zerlegt. Alternativen wären

<li>while statt for verwenden<pre>find . -depth -type d -print | sort | while read DIR ; do echo "$DIR" ; done</pre>
<li>über die Variable IFS das Zerlegen anhand der Blanks unterdrücken<blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">OIFS="$IFS"
IFS=""
for DIR in $(find . -type d -depth -print | sort) ; do
echo "$DIR"
done
IFS="$OIFS"</font><hr></pre></blockquote>

Beide Lösungen haben auch Nachteile. Die while-Schleife wird in der bash scheinbar durch eine Subshell abgearbeitet. Wenn man dort Variablen setzt, sind sie nach der while-Schleife wieder weg. In der zweiten Lösung wird IFS verändert, was zu Nebeneffekten bei folgenden Kommandos führen kann. Möglicherweise hilft es, wenn man IFS direkt im Schleifenkörper wieder restauriert und ncht erst am Ende der Schleife, wie im Beispiel oben. Das habe ich aber nicht ausprobiert.

Noch eine Anmerkung: Verwende einfach "." statt "$PWD". Das Ergebnis ist genau das gleiche, aber die Shell hat weniger zu tun.

Jochen

domseichter
Posts: 57
Joined: 11. Feb 2002 22:08
Location: Laufen
Contact:

Re: BASH: Alle Verzeichnisse in einem Verzeichnis finden, auch mit Leerzeichen

#3 Post by domseichter »

Hallo,

Vielen Dank, Jochen, Du hast mir sehr geholfen. Mein script läuft jetzt. Ich habe mir nämlich ein script gebastelt, dass meine komplette Mp3 Samlung in /home/dominik/Musik durchgeht und in für jedes Verzeichnis eine Playlist Datei (.m3u) erstellt. Jetzt kann ich meine Sammlung einfach in Juk importieren (wird Teil von KDE 3.2 sein) und hab schon alles nach Album und Interpret sortiert, da Juk die Playlist Dateien mit einliest.
Das fertige Script sieht so aus, vieleicht hat ja noch jemand Verbesserungs Vorschläge:
<blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">
#!/bin/bash

# Licensed under the GPL

echo "These script walks through a recursive directory tree"
echo "and creates a playlist m3u file for all mp3, ogg or wav"
echo "files it finds."
echo "(c) 2003 Dominik Seichter <domseichter@web.de>"

find $PWD -depth -type d -print | sort | while read DIR ;
do
pushd "$DIR"
listname=$(echo "$DIR" | awk -F "/" '{print $NF }' ).m3u;
find ./ -type f -maxdepth 1 | sed "s/.\///" | egrep -i -e "(.ogg|.mp3|.wav)" | sort | cat > ./"$listname";

# if playlist is empty, delete it
if [ -f "$listname" ];
then
if [ ! -s "$listname" ];
then
echo "Removing $listname again, because it is emtpy";
rm "$listname";
fi
fi
popd
done
</font><hr></pre></blockquote>

CU Dom
<!--http--><a href="http://www.kbarcode.net" target="_blank">kbarcode.net</a><!--url--> - <!--http--><a href="http://www.krename.net" target="_blank">krename.net</a><!--url-->

Jochen

Re: BASH: Alle Verzeichnisse in einem Verzeichnis finden, auch mit Leerzeichen

#4 Post by Jochen »

<li>Aus <pre>listname=$(echo "$DIR" | awk -F "/" '{print $NF }' ).m3u;</pre>würde ich <pre>listname=$(basename "$DIR").m3u</pre>machen. Das ist einfach lesbarer.

<li>Das "| cat" in der Folgezeile bitte ersatzlos streichen. Google mal nach "useless use of cat award" <img src="http://www.pl-forum.de/UltraBoard/Images/Happy.gif" border="0" align="middle">.

<li>Du treibst mit find, sed und egrep viel Aufwand. Wenn Du statt dessen der Shell sagst, sie soll bei Dateinamensauflösung case-insensitive arbeiten, geht das auch mit einem simplen ls. Ein <pre>shopt -s nocaseglob</pre> kommt vor die Schleife und statt des find/sed/egreps reicht dann ein <pre>ls *.{mp3,ogg,wav}</pre>Mit dem vorherigen Tipp kombiniert ergibt sich<pre>ls *.{mp3,ogg,wav} | sort > "$listname"</pre>als Ersatz für <pre>find ./ -type f -maxdepth 1 | sed "s/.\///" | egrep -i -e "(.ogg|.mp3|.wav)" | sort | cat > ./"$listname";</pre>Ein Unterschied ergibt sich nur in Spezialfällen, nämlich bei Directories, die auf .mp3/.wav/.ogg enden, und bei Sounddateien, die mit einem Punkt beginnen. Den zweiten Fall kann man mit <pre>shopt -s dotglob</pre>(ebenfalls nur einmal vor der Schleife) beheben.

Jochen

domseichter
Posts: 57
Joined: 11. Feb 2002 22:08
Location: Laufen
Contact:

Re: BASH: Alle Verzeichnisse in einem Verzeichnis finden, auch mit Leerzeichen

#5 Post by domseichter »

Hallo,

Den Befehl shopt kannte ich gar nicht, ist aber sehr nützlich. Vielen Dank für Deine neuen Tips, die machen mein Script um einiges einfach (obwohl ich so Stolz war find, sed, grep, awk und cat in einer Zeile untergebracht zu haben <img src="http://www.pl-forum.de/UltraBoard/Images/Wilk.gif" border="0" align="middle"> ).

CU Dom
<!--http--><a href="http://www.kbarcode.net" target="_blank">kbarcode.net</a><!--url--> - <!--http--><a href="http://www.krename.net" target="_blank">krename.net</a><!--url-->

Post Reply