bash "Karte" entspricht: führen Sie den Befehl für jede Datei
Habe ich oft einen Befehl, der verarbeitet eine Datei, und ich möchte, um Sie auf jede Datei in einem Verzeichnis. Gibt es eine integrierte Möglichkeit, dies zu tun?
Zum Beispiel, sagen wir ich habe ein Programm data
die Ausgänge eine wichtige Nummer zu einer Datei:
./data foo
137
./data bar
42
Möchte ich laufen, es auf jede Datei in dem Verzeichnis, in irgendeiner Art und Weise, wie diese:
map data `ls *`
ls * | map data
Ausbeute Ausgabe:
foo: 137
bar: 42
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie nur versuchen, führen Sie Ihr
data
Programm auf eine Reihe von Dateien, die einfachste/am wenigsten komplizierte Weg ist die Verwendung-exec
imfind
.Sagen, Sie wollten ausführen
data
auf alle txt-Dateien im aktuellen Verzeichnis (und Unterverzeichnisse). Das ist alles, was Sie brauchen:Wenn Sie wollte, Sie zu beschränken, um das aktuelle Verzeichnis, Sie könnten dies tun:
Es gibt viele Möglichkeiten, mit
find
.Wenn Sie nur wollen, um einen Befehl auszuführen, auf jede Datei, die Sie dies tun können:
Wenn Sie auch möchten, zur Anzeige der Dateinamen, der er derzeit arbeitet, dann könnte man auch dieses verwenden:
$i
so, dass Dateien mit Leerzeichen im Namen werden nicht behandelt, da mehrere Argumente, was auch immer das Programm aufgerufen wirdls
können sich in Klumpen expansion. Wenn Sie wirklich wollen, verwenden Sie die Ausgabe eines Befehls, die for-Schleife wird aufgeteilt auf alle eingebetteten Leerzeichen, so dass Sie wahrscheinlich wollen, setzen$IFS
nur Zeilenumbrüche, siehe meine Antwort, wenn nötig.Sieht es aus wie Sie wollen
xargs
:Drucken jedes Kommando zuerst, wird es ein wenig komplexer:
data
ist sicherlich zu begrüßen drucken Sie den aktuellen Dateinamen, wenn Sie es mag...Sollten Sie vermeiden,beim analysieren von
ls
:oder
Letztere nicht erstellen Sie eine subshell aus der while-Schleife.
Den gängigen Methoden sind:
Kann der zweite auf Probleme stoßen, wenn Sie Leerzeichen im Dateinamen; in diesem Fall würden Sie wahrscheinlich wollen, um sicherzustellen, dass es läuft in einer subshell, und stellen IFS:
Können Sie problemlos wickeln Sie das erste man in einem Skript:
ausgeführt werden kann wie gewünscht - nur vorsichtig sein, nie versehentlich ausführen etwas dumm mit ihm. Der Vorteil der Verwendung einer Schleifenkonstrukt ist, dass können Sie ganz einfach mehrere Befehle darin als Teil eines one-liner, im Gegensatz zu xargs, wo Sie haben, um Sie in ein ausführbares Skript für Sie zu laufen.
Natürlich können Sie auch einfach verwenden Sie das Dienstprogramm
xargs
:Beachten Sie, dass Sie sollten sicherstellen, dass die Indikatoren werden ausgeschaltet (
ls --indicator-style=none
) wenn Sie normalerweise verwenden, oder die@
angehängt, um Verknüpfungen zu nicht vorhandenen Dateinamen.for file in *
stattfor file in $(ls *)
grep -l
,find ...
, wer weiß.grep -l
undfind
werde ich +1 wenn Sie ersetzen Sie Sie in Ihre Antwort. Sie können analysieren, sicher Ihre gut definierten Ausgang.ls
hat ohne Papiere Ausgabe-format und somit ist eine andere Geschichte.GNU Parallel ist spezialisiert in der Herstellung dieser Art von Zuordnungen:
Es laufen wird, einen job auf jedem CPU-Kern parallel.
GNU Parallel ist ein Allgemeines parallelizer und macht ist einfach Aufträge ausführen, die parallel auf der gleichen Maschine oder auf mehreren Maschinen, die Sie haben ssh-Zugang zu.
Wenn Sie 32 verschiedene jobs, die Sie ausführen möchten, auf 4 CPUs, ein straight forward Weg zu parallelisieren ist zum ausführen von 8 jobs auf jeder CPU:
GNU Parallel statt erzeugt einen neuen Prozess, wenn eine Oberflächen - halten die CPUs aktiv und somit Zeit sparen:
Installation
Wenn GNU Parallel ist nicht als Paket für Ihre distribution, die Sie tun können, eine persönliche installation, die nicht erfordert root-Zugriff. Es kann getan werden, in 10 Sekunden durch, dies zu tun:
Für andere Installationsoptionen finden Sie unter http://git.savannah.gnu.org/cgit/parallel.git/tree/README
Erfahren Sie mehr
Siehe weitere Beispiele: http://www.gnu.org/software/parallel/man.html
Uhr die intro-videos: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
Spaziergang durch das tutorial: http://www.gnu.org/software/parallel/parallel_tutorial.html
Melden Sie sich für den E-Mail-Liste, um Unterstützung zu bekommen: https://lists.gnu.org/mailman/listinfo/parallel
Da Sie ausdrücklich gebeten, über diese in Bezug auf die "Karte", ich dachte, ich würde teilen, diese Funktion habe ich in meinem persönlichen shell-Bibliothek:
Ich diese in der Weise, dass Sie sich für eine Lösung:
Ich es mit dem Namen map_lines statt Karte, wie ich annahm, ich eines Tages zu implementieren, die eine map_args, wo Sie es benutzen würden, wie diese:
Diese Funktion würde wie folgt Aussehen:
Versuchen Sie dies:
Können Sie erstellen Sie ein shell-Skript etwa so:
Dass die Schleife durch jede Datei in /path/to/your/dir und führt deine "Daten" - Skript auf. Werden Sie sicher, dass chmod die oben genannten script, damit es ausführbar ist.
Könnten Sie auch PRLL.
ls
nicht handhaben Leerzeichen, Zeilenvorschübe und andere funky stuff in Dateinamen sollten vermieden werden, wo möglich.find
ist nur sinnvoll, wenn Sie mögen, Tauchen Sie ein in Unterverzeichnisse, oder wenn Sie wollen, machen Gebrauch von der anderen Optionen (mtime, - size, you name it).Aber viele Befehle, die den Umgang mit mehreren Dateien selbst, so brauchen Sie nicht eine for-Schleife:
aber
Ich habe nur geschrieben das Skript speziell auf die gleichen müssen.
http://gist.github.com/kindaro/4ba601d19f09331750bd
Es nutzt
find
zu bauen Satz von Dateien umsetzen, die es erlaubt, feinere Auswahl der Dateien, aus der die Zuordnung ermöglicht aber ein Fenster für schwieriger, Fehler zu machen, als gut.Entwarf ich zwei Betriebsarten: der erste Modus führt einen Befehl mit "Quelldatei" und "Zieldatei" Argumente, während der zweite Modus versorgt-source-Datei-Inhalt durch einen Befehl wie stdin und schreibt die Standardausgabe in eine Ziel-Datei.
Können wir weiter zu prüfen hinzufügen Unterstützung für parallele Ausführung und vielleicht Begrenzung der Satz von benutzerdefinierten Argumente finden ein paar die meisten notwendigen. Ich bin nicht wirklich sicher, ob das die richtigen Dinge zu tun.