Berechnen Sie Prüfsummen für eine zufällige Auswahl von Dateien, deren Namen in einer Datei aufgelistet sind

Berechnen Sie Prüfsummen für eine zufällige Auswahl von Dateien, deren Namen in einer Datei aufgelistet sind

Nehmen wir an, ich habe eine Datei mit dem Namen list_of_files.txt, wobei jede Zeile einer Datei auf der Festplatte entspricht. Beispiel:

dir1/fileA.ext1
dir1/subdir1/fileB.ext2
fileC.ext3
dir2/fileD.ext4
fileE.ext5

Ich möchte aus dieser Liste eine zufällige Anzahl von Dateien auswählen und deren Wert cksumberechnen .md5sum

Ich weiß, dass ich mit beispielsweise 3 Dateien nach dem Zufallsprinzip auswählen kann shuf -n 3 list_of_files.txt, aber wie kann ich erreichen, dass cksumsie als Dateinamen und nicht als Textinhalte behandelt werden?

Antwort1

Wenn Pfade in der Datei durch eine neue Zeile beendet und unverändert bereitgestellt werden, d. h. wenn jede Zeile ein separater wörtlicher Pfad ist, dann reicht eine Shell-Schleife aus:

shuf -n 3 list_of_files.txt | while IFS= read -r pth; do
   cksum "$pth"
done

Es gibt auch xargs(siehePOSIX-Spezifikationund fortgeschrittenerGNUxargs), Es gibtGNUparallel(NotizNicht-GNU parallelexistiertund ich beziehe mich nicht darauf). Mit dem richtigen Tool und den richtigen Optionen können Sie einem cksumProzess mehr als einen Pfad zuweisen (weniger cksumProzesse zu erzeugen ist im Allgemeinen von Vorteil) oder zwei oder mehr cksumProzesse parallel ausführen.

Um nur drei Dateien zu verarbeiten, bleibe ich aus Portabilitätsgründen vielleicht bei unserer Shell-Schleife; es sei denn, die Dateien sind groß und ich erwarte, dass drei cksumparallel laufende Prozesse wesentlich schneller sind als einer cksumgleichzeitig. Ich bin kein GNU-Experte parallel, aber es scheint eine ganz einfache Lösung zu geben:

 shuf -n 3 list_of_files.txt | parallel cksum

Standardmäßig parallelbegrenzt GNU die Anzahl gleichzeitiger Jobs durch die Anzahl der CPU-Kerne. Drei oder mehr Kerne sind heutzutage üblich, sodass der Befehl wahrscheinlich drei cksumProzesse parallel ausführen wird. Formal ist dies jedoch nicht portierbar. Beachten Sie auch, dass die parallele Verarbeitung von drei Dateien das parallele Lesen von drei Dateien bedeutet. E/A kann ein Engpass sein und dies kann den Nutzen paralleler Jobs verringern oder die Dinge sogar verschlimmern.

Auch dann parallelkann es sinnvoll sein. Verwenden Sie, -j 1um die Anzahl der Jobs auf 1 zu begrenzen:

 shuf -n 3 list_of_files.txt | parallel -j 1 cksum

Die Dateien werden wie in unserer Shell-Schleife sequentiell verarbeitet, aber die Syntax ist einfacher. Im Fall unserer Shell-Schleife müssen Sie wissen, was Sie wollenIFS= read -r pth, nicht nur read pth; und Sie müssen wissen, dass Sie (in vielen Schalen) wollencksum "$pth", nicht cksum $pth. Die Lösung mit GNU parallelist weniger fehleranfällig.KUSS.

Beachten Sie, xargsdass standardmäßig Anführungszeichen und Backslashs interpretiert werden und Leerzeichen als Trennzeichen betrachtet werden. Dies shuf -n 3 list_of_files.txt | xargs cksumist wahrscheinlich nicht das, was Sie wollen. Ihr Beispiel wird funktionieren, aber im Allgemeinen benötigen Sie zusätzliche Anführungszeichen und/oder Backslashs in der Datei; xor benötigen Sie, xargs -d '\n'wobei where -deine nicht portable Option von GNU ist xargs. Meine Annahme war „Pfade in der Datei werden durch Zeilenumbrüche beendet und so bereitgestellt, wie sie sind“. Mit dieser Annahme parallelfunktioniert GNU sofort (d. h. ohne zusätzliche Optionen), xargs nicht. Mit GNU xargskönnen Sie Folgendes tun:

shuf -n 3 list_of_files.txt | xargs -d '\n' cksum

Wenn Sie GNU verwenden können xargs(um die Situation zu retten -d '\n'), dann können Sie wahrscheinlich auch GNU verwenden parallel. Wenn Sie -j 1bei der Verwendung von GNU vergessen parallel, kann die Leistung des Befehls schlechter sein, aber er funktioniert trotzdem. Wenn Sie -d '\n'bei der Verwendung von GNU vergessen xargsund die Pfadnamen unverändert bereitgestellt werden, handelt es sich um einen Fehler. Aus diesem Grund empfehle ich parallelzuerst GNU.

GNU parallel kann nullterminierte Strings verarbeiten (die Option ist -0), ebenso GNU xargs( -0statt -d '\n') und GNU shuf( mit -z). Ihre Eingabedatei verwendet Zeilen, die durch Zeilenumbrüche terminiert sind, aber wenn Sie jemals mit Pfadnamen arbeiten müssen, die (möglicherweise) Zeilenumbruchzeichen enthalten, sollten Sie den Terminator in der Datei ändern und die entsprechenden Optionen hinzufügen.

verwandte Informationen