Xargs: Arbeitsverzeichnis vor der Ausführung in Dateipfad ändern?


4

Ich habe einen großen Ordner mit RAR-Archiven. Es gibt eine signifikante Hierarchie von Ordnerebenen. Ich möchte die gesamte Archivsammlung auf einmal entlarven.

Ich habe den folgenden Einzeiler, der funktionieren wird:

find -name "*.rar" -print0 | xargs -0 -n 1 -P 4 unrar x

(Beachten Sie, dass wir vier Threads gleichzeitig ausführen, um den Vorgang zu beschleunigen. :-))

Das Problem bei diesem Befehl ist, dass xargs für jede RAR-Datei im obersten Verzeichnis ausgeführt wird. Dies bedeutet, dass die gesamte Ausgabe in den Ordner der obersten Ebene verschoben wird.

Stattdessen soll die Ausgabe im selben Ordner wie das RAR-Archiv vorhanden sein.

Beispiel:

Top level
 |--FolderA
 |----File1.rar
 |----File2.rar
 |--FolderB
 |----File1.rar
 |----File2.rar
 |----File3.rar
 |--FolderC
 |----File1.rar
 |----File2.rar

Jede der "File1.rar" -Dateien enthält eine Datei mit demselben Namen. Das Extrahieren aller Dateien in den Ordner der obersten Ebene führt daher zu Überschreibproblemen.

Zusammenfassend möchte ich alle RAR-Dateien in der obigen Hierarchie extrahieren. Ich möchte, dass der Inhalt jeder RAR-Datei in dem Ordner vorhanden ist, in dem sich die RAR-Datei befindet.

Es scheint mir, dass die Lösung darin besteht, das Arbeitsverzeichnis irgendwie festzulegen und dann das unrar-Befehlsformular dort auszuführen. Da mir der Befehl find jedoch Dateinamen und keine Verzeichnisse gibt, kann ich so etwas nicht tun

| xargs -I{} -n 1 -P 4 cd {} \; unrar x {}

Gibt es einen besseren Weg, dies zu erreichen, als ein Perl- oder Python-Skript zu schreiben, das den Befehl unrar umgibt und den angegebenen Pfad in seine Teile aufteilt und den Befehl ausführt?

Antworten:


3

Es gibt Befehle zum Extrahieren eines Verzeichnisnamens ( dirname ) und Dateiname ( basename ) von einem Pfad. Sie könnten also so etwas tun

find . -name '*.rar' -print0 | \
xargs -0 -I{} -n1 -P4 /bin/sh -c 'cd "$(dirname {})"; unrar x "$(basename {})"'

SO VIEL ICH WEISS, xargs Da das Ändern von Verzeichnissen nicht unterstützt wird, benötigen Sie einen Vermittler, um dies zu tun /bin/sh. Sie haben erwähnt, einen Wrapper herumzuschreiben unrar, und das ist im Grunde, was dies tut, außer in Einzeilerform.


Genial! Genau das, was ich brauchte. Vielen Dank!
— fdmillion

Dies funktioniert, wenn die Pfadnamen keine Leerzeichen enthalten. Wenn Leerzeichen vorhanden sind, müssen Sie die Anführungszeichen anscheinend auf eine lächerliche Ebene anwählen: 'cd "$ (dirname" {} ")"; unrar x "$ (basename" {} ")" '(ich verwende unzip nicht unrar, aber den gleichen Unterschied)
— junichiro

1

Mit GNU Parallel sieht es so aus:

find . -name '*.rar' | parallel cd {//} '&&' unrar x {/}

GNU Parallel ist ein allgemeiner Parallelisierer, mit dem Sie auf einfache Weise Jobs auf demselben Computer oder auf mehreren Computern, auf die Sie ssh-Zugriff haben, parallel ausführen können.

Wenn Sie 32 verschiedene Jobs auf 4 CPUs ausführen möchten, können Sie auf einfache Weise 8 Jobs auf jeder CPU parallelisieren:

Simple scheduling

GNU Parallel erzeugt stattdessen einen neuen Prozess, wenn man fertig ist - die CPUs aktiv zu halten und damit Zeit zu sparen:

GNU Parallel scheduling

Installation

Wenn GNU Parallel nicht für Ihre Distribution gepackt ist, können Sie eine persönliche Installation durchführen, für die kein Root-Zugriff erforderlich ist. Dies kann in 10 Sekunden geschehen:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

Weitere Installationsoptionen finden Sie unter http://git.savannah.gnu.org/cgit/parallel.git/tree/README

Mehr erfahren

Weitere Beispiele: http://www.gnu.org/software/parallel/man.html

Sehen Sie sich die Intro-Videos an: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Gehen Sie durch das Tutorial: http://www.gnu.org/software/parallel/parallel_tutorial.html

Melden Sie sich für die E-Mail-Liste an, um Unterstützung zu erhalten: https://lists.gnu.org/mailman/listinfo/parallel


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.