Xargs: Ändern Sie das Arbeitsverzeichnis vor der Ausführung in den Dateipfad.

1299
fdmillion

Ich habe einen großen Ordner mit RAR-Archiven. Es gibt eine bedeutende Hierarchie von Ordnerebenen. Ich möchte die gesamte Archivsammlung gleichzeitig aufheben.

Ich habe den folgenden Einliner, der funktionieren wird:

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

(Beachten Sie, dass wir vier Threads parallel ausführen, um die Operation 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 gespeichert wird.

Stattdessen möchte ich, dass die Ausgabe im selben Ordner wie das RAR-Archiv vorhanden ist.

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. Wenn Sie sie alle in den Ordner der obersten Ebene extrahieren, treten Probleme beim Überschreiben auf.

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 der find-Befehl mir jedoch Dateinamen und keine Verzeichnisse gibt, kann ich so etwas nicht machen

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

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

3

2 Antworten auf die Frage

3
jjlin

Es gibt Befehle, um einen Verzeichnisnamen ( dirname) und einen Dateinamen ( basename) aus einem Pfad zu extrahieren . Also könntest du sowas machen

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

AFAIK xargsunterstützt das Wechseln der Verzeichnisse nicht, daher benötigen Sie dafür einen Vermittler /bin/sh. Sie haben erwähnt, ein Wrapper herumzuschreiben unrar, und das ist im Grunde das, was dies tut, außer in Einzeilerform.

Genial! Genau das, was ich brauchte. Vielen Dank! fdmillion vor 9 Jahren 0
Dies funktioniert, wenn die Pfadnamen keine Leerzeichen enthalten, und wenn Leerzeichen vorhanden sind, müssen Sie die Anführungszeichen anscheinend auf eine lobrische Ebene einwählen. 'Cd "$ (dirname" {} ")"; unrar x "$ (basename" {} ")" '(Ich verwende unzip nicht unrar, sondern den gleichen Unterschied) junichiro vor 6 Jahren 0
1
Ole Tange

Mit GNU Parallel sieht es so aus:

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

GNU Parallel ist ein allgemeiner Parallelisierer und ermöglicht das einfache Ausführen von Jobs auf demselben Computer oder auf mehreren Computern, auf die Sie über ssh zugreifen können.

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

Einfache Terminplanung

GNU Parallel erzeugt stattdessen einen neuen Prozess, wenn einer fertig ist - die CPUs bleiben aktiv und sparen Zeit:

GNU Parallele Planung

Installation

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

(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 finden Sie unter 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