[linux-l] Eure Erfahrungen mit digitalen Foto-Alben?

Volker Grabsch vog at notjusthosting.com
So Apr 23 18:07:03 CEST 2006


On Sun, Apr 23, 2006 at 02:51:18PM +0200, Frank Schubert wrote:
> Ich habe mal bei mir etwas herumexperimentiert
> 
> find /bilder/images2 -name '*.*' -print0 | xargs -0 -L 100 --  ln -s -b
> --target-directory=tmp_bilder/

Du machst sicherlich "-name *.*", um nur Dateien herauszufischen,
richtig? Das geht aber schief, wenn ein Verzeichnisname einen Punkt
enthält oder ein Dateiname keinen. Klingt zu theoretisch? Dann mach
mal:

cd /bilder/images2
find -name '*.*'

Gleich in der ersten Zeile kommt ".", das aktuelle Verzeichnis.

"man find" liefert einen besseren Weg:

    find /bilder/images2 -type f ...

Das listet nur reguläre Dateien auf. Möchtest du auch Symlinks, Sockets,
was-weiß-ich haben, dann lieber eine Negativ-Aussage. Also alles außer
Verzeichnisse:

    find /bilder/images2 ! -type d ...

> Nun liegen aber unterhalb von images2 verschiedene Verzeichnisse mit 
> identischen Namen.

Das ist noch ein Problem, ja.

> Kann man die (das entsprechende Verzeichnis und den Namen) eventuell via 
> pipe als ein neuen Neuen (zusammengesetzten Namen) neu generieren.

Nein, dafür nimmt man keine Pipes, sondern Backquotes, weil das Ergebnis
der Berechnungen nicht in die Standard-Eingabe wandern soll, sondern in
ein Befehls-Argument.

Problem: Jetzt kann nicht mehr ein "ln"-Befehl 100 Dateien handhaben.
Also:

    ... | xargs -0 -L 1 -- ln -s ...

Problem 2: wir wollen *nach* der Argumentliste noch eigene Argumente
anfügen. Das kann xargs auch, aber nur, wenn jedes Argument einen
einzelnen Befehl auslöst ... hey, kein Problem, brauchen wir ja eh.
Aber kann xargs auch Backquote-Aufrufe? Ich fürchte, folgendes wird
nicht klappen:

    ... | xargs -I file -- ln -s file `echo file | tr -d /`

Also vielleicht doch lieber "find --exec" hernehmen. Aber das hat
das gleiche Problem. Also doch eine Schleife:

    find ... | while read file; do ...; done


> Beispiel:
> 
> Durchsuche alle Unterverzeichnisse nach dateien und generiere dann z.B. aus:
> 
> unterverzeichnis/Bild1.jpg
>                 Bild2.jpg
> 
> dann
> 
> unterverzeichnisBild1.jpg
> unterverzeichnisBild2.jpg

Das ist ein sehr schön einfaches Schema. Es muss ja nur das "/" im Pfad
entfernt werden, also "tr -d /". Ich persönlich würde den "/" lieber
durch ein "_" ersetzen, also

    unterverzeichnis_Bild1.jpg

Das wäre dann "tr / _", also nur ein minimaler Unterschied.

Problem: Find darf keine absoluten Pfade zurückliefern. Es muss also
lokal gesucht werden:

    cd /bilder/images2 ; find ! -type d ...

Dann jedoch sehen die Resultate so aus:

    ./unterverzeichnis/Bild1.jpg

Das heißt, das "./" am Anfang muss noch weg, am einfachsten via:

    sed 's:^./::'


Ergebnis
========

cd /bilder/images2
find ! -type d | \
while read file; do
    ln -s "$file" "/home/ziel/`echo "$file" | sed 's:^./::' | tr / _`"
done


Das kommt mit Leerzeichen und anderen Sonderzeichen in den Dateinamen
klar. Nur bei Zeilenumbrüchen in Dateinamen gibt's Probleme. Also ist
es nicht 100%ig sauber. Würde "read" sowas wie "-0" haben, könnte es
mit "find -print0" zusammenarbeiten.

"read" hat aber die Option "-d" (siehe man bash), leider jedoch kann
man dort kein 0-Zeichen übergeben. :-(


Saubere Variante
================

Ganz sauber schafft man es IMHO nur mit zwei Scripten. Das eine enthält:

link.sh:
    ln -s "$2" "$1/`echo "$2" | sed 's:^./::' | tr / _`"

... und liegt im Pfad. Das zweite Script sähe dann so aus:

cd /bilder/images2
find ! -type d -exec \
link.sh /home/ziel '{}' ';'


Viele Grüße,

    Volker

-- 
Volker Grabsch
---<<(())>>---
Administrator
NotJustHosting GbR



Mehr Informationen über die Mailingliste linux-l