Bash hat eine Liste von Dateien aufgeteilt

8

Ich habe 200 Dateien in einem Ordner wie: test_1_cfg.dat, test_2_cfg.dat, .... und so weiter. Ich muss die ersten 40 Dateien als Eingabe in ein Bash-Skript aufnehmen und einen Prozess ausführen, ein anderes Skript, um die nächsten 40 Dateien zu lesen und einen anderen Prozess auszuführen.

Also habe ich mir überlegt, wie ich eine Liste mit den Namen der Dateien erstellen und diese Liste dann einfach aufteilen kann, aber ich bin mir nicht sicher, wie ich das in Bash machen soll.

Irgendeine Idee?

Alejandro
quelle

Antworten:

14

Methode 1 - Mit Kopf und Schwanz

Mit dem Befehl können Sie headdie ersten 40 Dateien aus einer Dateiliste wie folgt herausziehen:

$ head -40 input_files | xargs ...

Um die nächsten 40 zu bekommen:

$ tail -n +41 input_file  | head -40 | xargs ...

...

$ tail -n +161 input_file | head -40 | xargs ...

Mit derselben Technik können Sie die Liste 40 Mal gleichzeitig durchgehen.

Methode 2 - Verwenden von xargs

Wenn Sie zufällig alle Ihre Dateinamen in einer Variablen haben, können Sie xargswie folgt die Liste in Blöcke mit einer X-Anzahl von Elementen aufteilen.

Beispiel

Stellen Sie sich vor, meine Dateien heißen 1-200. Also lade ich sie in eine Variable wie folgt:

$ files=$(seq 200)

Sie können die ersten Elemente in dieser Variablen sehen:

$ echo $files  | head -c 20
1 2 3 4 5 6 7 8 9 10

Jetzt xargsteilen wir es auf:

$ xargs -n 40 <<<$files
1 2 3 4 5 6 7 8 9 10 ...
41 42 43 44 45 46 47 ...
81 82 83 84 85 86 87 ...
121 122 123 124 125 ...
141 142 143 144 145 ...
161 162 163 164 165 ...
181 182 183 184 185 ...

Sie könnten dann den obigen Befehl an einen anderen übergeben, xargsder dann Ihr Programm ausführen würde:

$ xargs -n 40 <<<$files | xargs ...

Wenn der Inhalt der xargsDateiliste über eine Variable nicht leicht zugänglich ist, können Sie stattdessen eine Liste über eine Datei erstellen:

$ xargs -n 40 <input_file
1 2 3 4 5 6 7 8 9 10 ...
41 42 43 44 45 46 47 ...
81 82 83 84 85 86 87 ...
121 122 123 124 125 ...
141 142 143 144 145 ...
161 162 163 164 165 ...
181 182 183 184 185 ...

Methode 3 - Bash-Arrays

Angenommen, Sie hatten Ihre Dateinamen in einem Bash-Array. Wieder verwende ich eine Sequenz mit der Nummer 1-200, um meine Dateinamen darzustellen.

$ foo=( $(seq 200) )

Sie können den Inhalt des Arrays folgendermaßen sehen:

$ echo ${foo[@]}
1 2 3 4 5 ....

Nun zum 1. 40:

$ echo "${foo[@]:0:40}"

Die 2. 40 usw.:

$ echo "${foo[@]:40:40}"
...
$ echo "${foo[@]:160:40}"
slm
quelle
Ich mag die Xargs-Akrobatik sehr, aber Bash-Arrays sind auch nützlich. Hier gibt es etwas zu lernen!
Matthias Kauer
8

Dies ist ein perfektes Rezept für xargs:

cat list_of_files | xargs -n 40 command

Zitat aus man xargs:

 -n number   Set the maximum number of arguments taken from standard input
             for each invocation of the utility.  An invocation of utility
             will use less than number standard input arguments if the
             number of bytes accumulated (see the -s option) exceeds the
             specified size or there are fewer than number arguments
             remaining for the last invocation of utility.  The current
             default value for number is 5000.

Um für jeden Satz unterschiedliche Aktionen auszuführen, müssen Sie relevante Zeilen abrufen, bevor Sie diese an folgende Adresse übergeben xargs:

 sed -n '1,40p' list_of_files | xargs command1
 sed -n '41,80p' list_of_files | xargs command2
 ...     
devnull
quelle
groß!!! Vielen Dank. Ich kann jetzt die Dateien teilen, aber wie kann ich zum Beispiel den zweiten Satz von 40 Dateien für das andere Skript auswählen?
Alejandro
1
@Alejandro Siehe Update.
devnull
2

Zu Ihrer Information, ich liebe das, xargs -n 40 <<<$filesaber da es "40 Argumente" pro Zeile macht, habe ich es getan

threads=10
xargs -n $((40/threads)) <<<$files

oder wenn in einem Array ..

n=(1 2 3 4 5 6)
xargs -n $((${#n[@]}/threads))

while read -r input; do
  for item in $input; do
    <..stuff..>
  done &
done <<< $(for x in ${n[@]}; do echo $x; done | xargs -n $((${#n[@]}/threads)))
wait
user3653982
quelle
2
Bitte versuchen Sie, die Lesbarkeit zu verbessern, indem Sie Codebeispiele als solche formatieren (s. Unix.stackexchange.com/editing-help - oder klicken Sie auf das? In der oberen / rechten Ecke des Editors)
sborsky