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

[solved] alle Dateien mit einer Endung aus einem Ordner verschieben, Verzeichnisstruktur auflösen

Liebe Gemeinde,
eine Frage im Terminal bitte:

wie ihr seht habe ich Musikdateien in diversen unterordnern... Ich möchte gerne
1) Recursiv alle Dateien, die im Ordner "Abba" sind als Liste (ls) ohne tree anzeigen
2) diese Dateien mit einem Aufruf aus allen Unterordnern (Achtung auf den Ordner "Falle") in den Elternordner test verschieben
3) Soviel ich herausgefunden habe kennt "mv" kein Rekursiv --> muss man zuerst die dateien mit cp -r kopieren, und dann im ursprünglichen Verzeichnis löschen?
4) gibt es etwas wie Recursiv oder dry-run im befehl "mv" oder "cp"

Code:
adi@adi-pc:~$ tree test
test
├── Abba
│   ├── Abba - The Winner Takes It All.mp3
│   ├── Absolute CD1
│   │   ├── Abba - Absolute CD 1 - 01 - Fernando.wma
│   │   ├── Abba - Absolute CD 1 - 02 - The name of the game.wma
│   │   ├── Abba - Absolute CD 1 - 03 - Chiquitita.wma
│   │   ├── Abba - Absolute CD 1 - 04 - Thank you for the music.wma
│   │   ├── Abba - Absolute CD 1 - 05 - Angel eyes.wma
│   │   └── Falle
│   │       ├── Abba - Absolute CD 1 - 06 - Waterloo.wma
│   │       ├── Abba - Absolute CD 1 - 07 - Knowing me knowing you.wma
│   │       ├── Abba - Absolute CD 1 - 08 - One of us.wma
│   │       ├── Abba - Absolute CD 1 - 09 - Does your mother know.wma
│   │       ├── Abba - Absolute CD 1 - 10 - Summer night city.wma
│   │       ├── Abba - Absolute CD 1 - 11 - Lay all your love on me.wma
│   │       └── Abba - Absolute CD 1 - 12 - Winner takes it all.wma
│   └── Absolute CD2
│       ├── Abba - Absolute CD2 - 01 - Super trouper.wma
│       ├── Abba - Absolute CD2 - 02 - Money money money.wma
│       ├── Abba - Absolute CD2 - 03 - Voulez vous.wma
│       ├── Abba - Absolute CD2 - 04 - Ring ring.wma
│       ├── Abba - Absolute CD2 - 05 - Head over heels.wma
│       ├── Abba - Absolute CD2 - 06 - Take a chance on me.wma
│       ├── Abba - Absolute CD2 - 07 - Dancing queen.wma
│       ├── Abba - Absolute CD2 - 08 - Gimme! gimme! gimme!.wma
│       ├── Abba - Absolute CD2 - 09 - Mamma mia.wma
│       ├── Abba - Absolute CD2 - 10 - I do I do I do.wma
│       ├── Abba - Absolute CD2 - 11 - SOS.wma
│       └── Abba - Absolute CD2 - 12 - I have a dream.wma
└── mymusic

Danke und Lg
 
A

Anonymous

Gast
was willst du denn rekursiv verschieben? , wenn du ein Verzeichnis verschiebst, dann verschiebst du automatisch alle Dateien und Unterordner mit deren Dateien automatisch mit. also ist dieses schon rekursiv genug, eine Steigerung dazu gibt es nicht mehr.

robi
 
OP
MuppetShow12

MuppetShow12

Newbie
Die Dateien will ich rekursiv aus allen Unterordnern in den "Hauptordner" oder "root" schieben - das muss man in manchen Fällen mit Audiodateien auf Usb-Sticks machen, weil manche AVRs nur Random innerhalb von Ordnern (in dem Fall Alben) und nicht alle Tracks der Künstler randomizen. Folgender Befehl hat nicht funktioniert:
Code:
adi@adi-pc:~/test$ cp -Riv ./Abba/*.wma ./
Lg
 
A

Anonymous

Gast
verschieben
Code:
find ./Abba  -name "*.wma" -exec mv -i {}  Zielverzeichnis \;
oder kopieren
Code:
find ./Abba  -name "*.wma" -exec cp -i {} Zielverzeichnis  \;

in beiden Fällen bitte mit Option -i arbeiten, dabei würdest du gefragt werden wenn es eine Datei mit dem selben Namen schon im Zielverzeichnis geben würde. beim Verschieben würdest du sonst die erste Datei komplett verlieren, beim Kopieren würde im Ergebnis die erste Datei nicht vorhanden sein.
Normalerweise mach man sowas aber nicht, das man sich hier einmal sortierte Dateien auf diese Art wieder vermischt, Dafür gibt es Abspiellisten die solche Geräte beherrschen.

robi
 
OP
MuppetShow12

MuppetShow12

Newbie
Hi Robi danke!
Verständnisfrage bitte: Gibt es mit cp -R keine Möglichkeit? - Ich dachte recursiv geht man in alle Unterordner hinein und kopiert die beinhalteten Dateien heraus? Wenn nicht - wofür verwendet man cp -r sonst?
Lg adi
 
A

Anonymous

Gast
cp -r verwendet man wenn man einen Verzeichnisbaum mit samt Unterverzeichnisse 1 zu 1 kopieren will. genau das willst du aber nicht, du willst die Verzeichnisstruktur ja auflösen.

robi
 
OP
MuppetShow12

MuppetShow12

Newbie
mittlerweile habe ich von einem Bekannten erfahren was {} und \; zu bedeuten haben...
-exec und {} gehören zum find dazu; {} steht für die aktuell gefundene Datei - das bedeutet also dass man den Befehl (unter -exec) mit der gefundenen Datei ausführt.
"\" heißt dass man eine Ebene herausgeht -> das Zeichen danach, in diesem Fall ";" wird nicht im Copy-Befehl interpretiert sondern eine Ebene höher (d.h. im find) ausgeführt.... ich hoffe, ich hab das richtig verstanden, wenn nicht bitte Antworten.
Lg
 
A

Anonymous

Gast
find gehört zu den paar 100 sehr speziellen aber sehr mächtigen Befehlen mit sehr vielen Optionen. Es wird gerne verwendet aber selten wirklich im vollen Umgang genutzt, da es in bestimmten Bereichen doch recht kompliziert ist.

oft Verwendung findet folgender Befehlsaubau.

Code:
find VERZEICHNIS  [OPTION .....] -exec BEFEHL {} \;
Die Dateinamen die dabei mit den Optionen ausgefiltert werden, werden dabei einzeln in einem eigenen Prozess mit dem BEFEHL gestartet und zwar dort wo {} steht. das ; zeigt dabei find wo der Befehl zu ende ist und es gegebenenfalls weiter nach noch folgenden weiteren find-Optionen suchen soll.
Das \ vor dem ; wird aus dem Grunde benötigt, da die gesamte Befehlszeile schon beim Start von der Bash interpretiert wird. Und in der Bash ist das ; ein Trenner der einzelne Befehle trennt. Damit das ; nun wirklich bis zum find durchgereicht werden kann muss, es vor der Interpretation der Bash geschützt werden. genau das mach das \ .

Ausgeführt wird dabei der Reihe nach von find
Code:
BEFEHL  DATEI_1 :
BEFEHL  DATEI_2 ;
.....
BEFEHL DATEI_n ;

Es werden also entsprechend der gefunden Dateinamen jeweils ein eigener Prozess für jeden Dateinamen gestartet. Das reicht meistens den Anforderungen kann aber den großen Nachteil haben, dass dieses sehr lange dauern kann, wenn zB sehr viel Dateinamen gefunden werden. ls ist hier kein allzugutes Beispiel, aber auch hier können wir durchaus schon gravierende Laufzeitunterschiede ermitteln. Wesentlich gravierende Unterschiede würde man zB bei richtigen Dateioperationen zB rm bekommen.

Beispiel:
Code:
robi@lux001:~> time find /home/robi -type f  -exec ls -l {} \;
.........
real    0m8.319s
user    0m2.445s
sys     0m3.602s
( erst den 2, Aufruf dieses Befehles verwenden, dann ist das Dateisystem gecacht und muss nicht neu von Platte gelesen werden, die Zeiten sind dann für Tests vergleichbar)

Es geht aber auch schneller, wenn man statt jeden Dateinamen einzeln in einem Prozess zu bearbeiten, man einfach alle Dateinamen mit nur einem Prozess (bzw. mit nur ein paar wenigen) bearbeiten würde.
Code:
ls -l DATEI_1 DATEI_2 ......DATEI_n

Auch dieses kann find . wenn man statt dem \; ein + verwendet ( Das + kann man, aber muss es nicht vor der Bash schützen, da es in der Bash an dieser Stelle nicht interpretiert wird.)
Code:
robi@lux001:~> time find /home/robi -type f  -exec ls -l {} +
real    0m0.162s
user    0m0.088s
sys     0m0.052s
Wie man sieht ist dieses in diesem Test um ein Vielfaches (ca. 50x) schneller.

Diese Funktion mit -exec {} + wird in der Praxis bei find jedoch selten benutzt und ist auch nicht so sehr bekannt, Auch weil es hierfür eine bekannte und noch weit mächtigere und sehr umfangreich konfigurierbare Alternative mittels xargs gibt. Dieser Befehl wird immer dann wichtig, wenn extrem viele Dateinamen mit einem Befehl abgearbeitet werden sollen.
Linux hat nämlich eine Grenze welche die Länge der Kommandozeile betrifft. ( auszulesen mit "getconf ARG_MAX")
wird die Kommandozeile länger, wird eine Fehlermeldung ausgegeben, dass die Kommandozeile zu lang ist.
Code:
obi@lux001:~> time find /home/robi -type f | xargs ls -l
real    0m0.162s
user    0m0.088s
sys     0m0.052s
Mit xargs könnte man jetzt unter anderem bestimmen, wie viele Dateinamen jetzt mit einem einzigem BEFEHL bearbeitet werden sollen und könnte diese Befehle bei Bedarf dann auch noch parallel abarbeiten.
Hier zB 500 Dateinamen mit 8 Prozessen parallel.
Code:
time find /home/robi -type f | xargs -n 500 -P 8  ls -l
real    0m0.073s
user    0m0.137s
sys     0m0.082s

Aber jetzt endlich genug der Theorie und Schulmeisterei, ;)

robi
 
Oben