• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[gelöst] massenweise Links erstellen mit find und xargs

Hallo,

ich möchte ein großes Verzeichnis mit vielen Unterverzeichnissen (und Leerzeichen im Namen) durchackern lassen und in jedem Unterverzeichnis das eine Datei xy.jpg enthält einen Link xyz.jpg dazu an selber Stelle erstellen. Das ganze soll per cron regelmäßig ausgeführt werden um bei neu hinzukommenden Dateinen die passenden Links automatisch erzeugt zu bekommen.

Ich denke ich mache das besser mit cp statt ln weil, cp die Option -u kennt und damit hoffentlich die vorhandenen Links nicht unnötig neu anlegen würde. Für das Durchackern wird man find und xargs nehmen denke ich, wegen der Leerzeichen -print0 und -0. Leider habe ich Probleme mir aus diesen Grundlagen eine funktionstüchtig Befehlszeile zusammen zu schustern :-/ Es hapert an dem Punkt, dass ich die Links nicht an einem Zielort sammeln, sondern in den jeweiligen Ordnern bei den Originalen erzeugen will. Wie gebe ich cp das Ziel mit Pfad an wenn die Quelle von xargs kommt und den falschen (noch nicht auf xyz geänderten) Dateinamen enthält? Muss ich dafür mit sed rumbasteln oder gibt es eine Möglichkeit den Pfad vom Namen automatisch zu trennen? Oder kann ich cp gleich mitgeben, dass der Zielpfad dem Quellpfad entsprechen soll?

Danke :)
 
Hallo catalpa,

catalpa schrieb:
ich möchte ein großes Verzeichnis mit vielen Unterverzeichnissen (und Leerzeichen im Namen) durchackern lassen und in jedem Unterverzeichnis das eine Datei xy.jpg enthält einen Link xyz.jpg dazu an selber Stelle erstellen.
So:
Code:
find ~ -iname xyz.jpg -print0 | xargs -0 -I {} ln -s '{}'.lnk

catalpa schrieb:
Ich denke ich mache das besser mit cp statt ln weil, cp die Option -u kennt und damit hoffentlich die vorhandenen Links nicht unnötig neu anlegen würde.
Also so:
Code:
find ~ -iname xyz.jpg -print0 | xargs -0 -I {} cp -n '{}'.kopie
Aber eine Kopie ist doch kein Link!
Dann eventuell in der Art (ungetestet):
Code:
find ~ -iname xyz.jpg -print0 | xargs -0 -I {} $(for a in {}; do cp -n {} "$(echo {}; done

catalpa schrieb:
Es hapert an dem Punkt, dass ich die Links nicht an einem Zielort sammeln, sondern in den jeweiligen Ordnern bei den Originalen erzeugen will.
Den Pfad kann man doch über eine Variable mitnehmen.

lieben Gruß aus Hessen
 
A

Anonymous

Gast
catalpa schrieb:
Ich denke ich mache das besser mit cp statt ln weil, cp die Option -u kennt und damit hoffentlich die vorhandenen Links nicht unnötig neu anlegen würde
unnötig, ln legt link nur neu an wenn die Option -f mitgegeben wird, sonst gibt ln eine Fehlermeldung aus, das Zieldatei schon existiert. Entweder also den Fehlerkanal von ln auf /dev/null legen, oder bei find ausschließen das Dateien mit schon 2 Namen gefunden werden, (find DIR -name xy.jpg -links 1 ...... )
catalpa schrieb:
Für das Durchackern wird man find und xargs nehmen denke ich, wegen der Leerzeichen -print0 und -0.
unnötig wenn es sich nur um Leerzeichen handeln sollte.
catalpa schrieb:
Leider habe ich Probleme mir aus diesen Grundlagen eine funktionstüchtig Befehlszeile zusammen zu schustern :-/ Es hapert an dem Punkt, dass ich die Links nicht an einem Zielort sammeln, sondern in den jeweiligen Ordnern bei den Originalen erzeugen will.
einfach bei find mit -execdir arbeiten. Würde sich prima anbieten wenn wirklich der Neue Name schon fest steht, und nicht aus dem orginalnamen zusammengebaut werden soll.
catalpa schrieb:
Wie gebe ich cp das Ziel mit Pfad an wenn die Quelle von xargs kommt und den falschen (noch nicht auf xyz geänderten) Dateinamen enthält? Muss ich dafür mit sed rumbasteln oder gibt es eine Möglichkeit den Pfad vom Namen automatisch zu trennen? Oder kann ich cp gleich mitgeben, dass der Zielpfad dem Quellpfad entsprechen soll?
es gibt zig Wege das zu tun, mit sed rumbasteln ist die bekannteste, aber auch langsamste und würde in diesem Fall nur gehen wenn du ein ganzes Script schreibst, da du innerhalb des find-Konstruktes nicht richtig arbeiten kannst. 2. Möglichkeit wäre dieses mit der Bash selbst zu bearbeiten, ( Stichwort: Parameter Expansion ) sehr elegant und schnell, aber auch schwierig innerhalb von find. 3. Möglichkeit dieses mit der Bash und den Befehlen basename und dirname zu erledigen, ist aber auch nur im Script möglich.

also alles in einem Ritt und nur mit find
Code:
/usr/bin/find DIR  -name "xy.jpg" -links 1 -execdir ln {} xyz.jpg \;

robi
 
Ich danke euch für die schnellen Antworten, echt toll :)

>Aber eine Kopie ist doch kein Link!
mit Schalter -s hätte ich Links erzeugt statt Kopien

Code:
/usr/bin/find DIR  -name "xy.jpg" -links 1 -execdir ln {} xyz.jpg \;

das sieht sehr elegant aus, mal sehen ob ich es halbwegs verstehe:

"-links 1"
frage: stellt die Ursprungsdatei alleine bereits EINEN Link da, so dass eine Datei die schon 1x verlinkt wurde ein -links 2 erfordern würde?

"-execdir"
legt einfach das Ausführungsverzeichnis fest, top! Das ist sehr schön gelöst...

"{}"
enthält den ganzen Pfad was nicht nötig wäre, wegen dem -execdir, was aber auch nicht schadet

"\;"
wozu ist das?

vielen Dank
 

framp

Moderator
Teammitglied
catalpa schrieb:
...
"\;"
wozu ist das?...
Lt
Code:
man find
muss u.A. bei execdir der Befehl mit einem ; bendet werden. Da das ; normalerweise in der bash mehrere Befehle trennt muss es mit \ 'escaped' werden damit die bash das nicht als einen solchen Befehlsseparator interpretiert. Sieht merkwuerdig aus - aber wenn man es einmal weiss vergisst man es nicht mehr.
 
A

Anonymous

Gast
catalpa schrieb:
aber ich glaube bei "-links" muss es "0" statt "1" sein
den Wert dort musst du als Anzahl der aktuellen Namen für diese Datei interpretieren. 0 würde bedeuten, die Datei existiert hat aber keinen Namen, ist also schon gelöscht die Datei aber noch von einem aktiven Prozess geöffnet.
das ist auch der Wert der bei " ls -l " gleich hinter den Zugriffsrechten angezeigt wird.

robi
 
Hallo,

dann klappt der Trick mit -links 1 aber nicht, weil bei schon
bestehenden Links (symbolische) hagelt es Fehler...
 
Warum versuchen Leute immer, solch komplexe Sachen in einer einzigen Zeile zu machen (und wundern sich dann, daß weder 0 noch 1 das gewünschte Ergebnis liefert)?
 
A

Anonymous

Gast
abgdf schrieb:
wundern sich dann, daß weder 0 noch 1 das gewünschte Ergebnis liefert?
Das ist EDV, da gibt es nur Nullen und Einsen also entweder oder, und wenn nicht, dann wurde die falsche Frage gestellt. Aufgabe lautetet
" und in jedem Unterverzeichnis das eine Datei xy.jpg enthält einen Link xyz.jpg dazu an selber Stelle erstellen."
wo ist dort beschrieben, das es dort jetzt auch schon noch Symlinks mit namens xyx.jpg gibt?

Lösung könnte lauten "ln ......... >/dev/null" aber das müsste man sich an den orginaldaten anschauen, besser ist natürlich wenn man sich für ein einheitliches Konzept entweder Hard oder Symlinks oder was auch immer, sonst ist es nicht mehr mit einer Zeile zu erledingen und man muss erst Perl lernen.

robi
 
Habe inzwischen auch gemerkt dass es an den Softlinks liegt, sorry hatte vergessen dass ich solche anlegen wollte. Weitere gibt es nicht, nur die frisch angelegten. Ich könnte auf Hartlinks umstellen würde keinen Unterschied in der Nutzung machen, oder die Fehler umleiten ist im Grunde egal.

vielen Dank nochmal :)

(bitte auf gelöst setzen)
 
Oben