Könnte jemand bitte den Code bereitstellen, um Folgendes zu tun: Angenommen, es gibt ein Verzeichnis von Dateien, die alle über ein Programm ausgeführt werden müssen. Das Programm gibt die Ergebnisse als Standard aus. Ich benötige ein Skript, das in ein Verzeichnis geht, den Befehl für jede Datei ausführt und die Ausgabe in einer großen Ausgabedatei zusammenfasst.
So führen Sie den Befehl beispielsweise für eine Datei aus:
$ cmd [option] [filename] > results.out
ls <directory> | xargs cmd [options] {filenames put in here automatically by xargs} [more arguments] > results.out
ls
wahrscheinlich nicht zum Fahren verwendenxargs
. Wenncmd
es überhaupt kompetent geschrieben ist, können Sie es vielleicht einfach tuncmd <wildcard>
.Antworten:
Der folgende Bash-Code übergibt $ file an den Befehl, wobei $ file jede Datei in / dir darstellt
Beispiel
quelle
/dir/
, wird die Schleife immer noch einmal mit dem Wert '*' für ausgeführt$file
, was möglicherweise unerwünscht ist. Um dies zu vermeiden, aktivieren Sie nullglob für die Dauer der Schleife. Fügen Sie diese Zeile vor der Schleifeshopt -s nullglob
und diese Zeile nach der Schleife hinzushopt -u nullglob #revert nullglob back to it's normal default state
.done >results.out
(und wahrscheinlich können Sie sie überschreiben, anstatt sie anzuhängen, wie ich hier angenommen habe).Wie wäre es damit:
-maxdepth 1
Das Argument verhindert, dass find rekursiv in Unterverzeichnisse absteigt. (Wenn Sie möchten, dass solche verschachtelten Verzeichnisse verarbeitet werden, können Sie dies weglassen.)-type -f
Gibt an, dass nur einfache Dateien verarbeitet werden.-exec cmd option {}
Weist es an,cmd
mit deroption
für jede gefundene Datei angegebenen Datei auszuführen , wobei der Dateiname ersetzt wird{}
\;
bezeichnet das Ende des Befehls.cmd
Ausführungen umgeleitetresults.out
Wenn Sie sich jedoch für die Reihenfolge interessieren, in der die Dateien verarbeitet werden, ist es möglicherweise besser, eine Schleife zu schreiben. Ich denke,
find
verarbeitet die Dateien in Inode-Reihenfolge (obwohl ich mich darin irren könnte), was möglicherweise nicht das ist, was Sie wollen.quelle
stat
und erfolgensort
, was natürlich von den Sortierkriterien abhängt.-exec
Option verknüpfen ? Muss ich sie in einfache Anführungszeichen setzen oder so?find
ist immer die beste Option, da Sie mit der Option nach Dateinamenmuster filtern-name
und dies in einem einzigen Befehl tun können.-exec
Optionen hinzufügen :find . -name "*.txt" -exec echo {} \; -exec grep banana {} \;
Ich mache das auf meinem Himbeer-Pi von der Kommandozeile aus, indem ich Folgendes ausführe:
quelle
Die akzeptierten / hoch bewerteten Antworten sind großartig, aber es fehlen ein paar Details. Dieser Beitrag behandelt die Fälle, wie Sie besser damit umgehen können, wenn die Erweiterung des Shell-Pfadnamens (Glob) fehlschlägt, wenn Dateinamen eingebettete Zeilenumbrüche / Strichsymbole enthalten und die Umleitung der Befehlsausgabe aus der for-Schleife verschoben wird, wenn die Ergebnisse in a geschrieben werden Datei.
Wenn Sie die Shell-Glob-Erweiterung mit ausführen, besteht die
*
Möglichkeit, dass die Erweiterung fehlschlägt, wenn keine Dateien im Verzeichnis vorhanden sind und eine nicht erweiterte Glob-Zeichenfolge an den auszuführenden Befehl übergeben wird, was zu unerwünschten Ergebnissen führen kann. Diebash
Shell bietet hierfür eine erweiterte Shell-Optionnullglob
. Die Schleife wird also im Grunde genommen wie folgt in dem Verzeichnis, das Ihre Dateien enthältAuf diese Weise können Sie die for-Schleife sicher verlassen, wenn der Ausdruck
./*
keine Dateien zurückgibt (wenn das Verzeichnis leer ist).oder auf POSIX-konforme Weise (
nullglob
istbash
spezifisch)Auf diese Weise können Sie in die Schleife gehen, wenn der Ausdruck einmal fehlschlägt, und die Bedingung
[ -f "$file" ]
überprüfen, ob die nicht erweiterte Zeichenfolge./*
ein gültiger Dateiname in diesem Verzeichnis ist, was nicht der Fall wäre. Wenn diese Bedingung fehlschlägt, kehrencontinue
wir zu derfor
Schleife zurück, die anschließend nicht ausgeführt wird.Beachten Sie auch die Verwendung von
--
kurz vor dem Übergeben des Dateinamenarguments. Dies ist erforderlich, da die Shell-Dateinamen, wie bereits erwähnt, an beliebiger Stelle im Dateinamen Bindestriche enthalten können. Einige der Shell-Befehle interpretieren dies und behandeln sie als Befehlsoption, wenn der Name nicht richtig in Anführungszeichen gesetzt wird, und führen den Befehl aus, wenn das Flag bereitgestellt wird.Das
--
signalisiert in diesem Fall das Ende der Befehlszeilenoptionen. Dies bedeutet, dass der Befehl keine Zeichenfolgen über diesen Punkt hinaus als Befehlsflags, sondern nur als Dateinamen analysieren sollte.Das doppelte Zitieren der Dateinamen löst die Fälle, in denen die Namen Glob-Zeichen oder Leerzeichen enthalten. * Nix-Dateinamen können aber auch Zeilenumbrüche enthalten. Daher beschränken wir Dateinamen mit dem einzigen Zeichen, das nicht Teil eines gültigen Dateinamens sein kann - dem Null-Byte (
\0
). Dabash
intern StilzeichenfolgenC
verwendet werden, in denen die Nullbytes verwendet werden, um das Ende der Zeichenfolge anzugeben, ist dies der richtige Kandidat dafür.So mit der
printf
die Möglichkeit , Shell abgrenzen Dateien mit diesem NULL - Byte mit-d
Optionread
Befehl können wir tun untenDie
nullglob
und dieprintf
werden umbrochen,(..)
was bedeutet, dass sie im Grunde genommen in einer Unter-Shell (untergeordnete Shell) ausgeführt werden, da nach demnullglob
Beenden des Befehls die Option vermieden wird, über die übergeordnete Shell nachzudenken. Die-d ''
Befehlsoptionread
ist nicht POSIX-kompatibel und benötigt daher einebash
Shell, um dies zu tun. Mit demfind
Befehl kann dies wie folgt erfolgenFür
find
Implementierungen, die nicht unterstützt werden-print0
(außer den GNU- und FreeBSD-Implementierungen), kann dies mit emuliert werdenprintf
Ein weiterer wichtiger Fix besteht darin, die Neuausrichtung aus der for-Schleife zu verschieben, um eine hohe Anzahl von Datei-E / A zu reduzieren. Bei Verwendung innerhalb der Schleife muss die Shell Systemaufrufe zweimal für jede Iteration der for-Schleife ausführen, einmal zum Öffnen und einmal zum Schließen des der Datei zugeordneten Dateideskriptors. Dies wird zu einem Engpass für Ihre Leistung beim Ausführen großer Iterationen. Empfohlener Vorschlag wäre, es außerhalb der Schleife zu verschieben.
Sie können den obigen Code mit diesen Korrekturen erweitern
Dadurch wird der Inhalt Ihres Befehls für jede Iteration Ihrer Dateieingabe auf stdout gesetzt. Wenn die Schleife endet, öffnen Sie die Zieldatei einmal, um den Inhalt des stdout zu schreiben und zu speichern. Die äquivalente
find
Version davon wärequelle
Ein schneller und schmutziger Weg, der die Arbeit manchmal erledigt, ist:
Um beispielsweise die Anzahl der Zeilen in allen Dateien im aktuellen Verzeichnis zu ermitteln, haben Sie folgende Möglichkeiten:
quelle
~/.local/share/steam
. Ran Steam. Es löschte alles auf dem System, das dem Benutzer gehört." Fehlerbericht.Ich musste alle .md-Dateien von einem Verzeichnis in ein anderes kopieren, also habe ich Folgendes getan.
for i in **/*.md;do mkdir -p ../docs/"$i" && rm -r ../docs/"$i" && cp "$i" "../docs/$i" && echo "$i -> ../docs/$i"; done
Was ziemlich schwer zu lesen ist, also lasst es uns zusammenfassen.
erste CD in das Verzeichnis mit Ihren Dateien,
for i in **/*.md;
für jede Datei in Ihrem Mustermkdir -p ../docs/"$i"
Erstellen Sie dieses Verzeichnis in einem Dokumentordner außerhalb des Ordners, der Ihre Dateien enthält. Dadurch wird ein zusätzlicher Ordner mit demselben Namen wie diese Datei erstellt.rm -r ../docs/"$i"
Entfernen Sie den zusätzlichen Ordner, der als Ergebnis von erstellt wurdemkdir -p
cp "$i" "../docs/$i"
Kopieren Sie die eigentliche Dateiecho "$i -> ../docs/$i"
Echo was du getan hast; done
Lebe glücklich bis ans Endequelle
**
funktioniert, muss dieglobstar
Shell-Option festgelegt werden:shopt -s globstar
Sie können verwenden
xarg
ls | xargs -L 1 -d '\n' your-desired-command
-L 1
bewirkt, dass jeweils 1 Element übergeben wird-d '\n'
make output ofls
wird basierend auf der neuen Zeile aufgeteilt.quelle
Basierend auf dem Ansatz von @Jim Lewis:
Hier ist eine schnelle Lösung zum Verwenden
find
und Sortieren von Dateien nach ihrem Änderungsdatum:Zum Sortieren siehe:
http://www.commandlinefu.com/commands/view/5720/find-files-and-list-them-sorted-by-modification-time
quelle
-print0
fürfind
und-0
fürxargs
welche Nullzeichen anstelle von Leerzeichen (einschließlich Zeilenumbrüchen) verwendet werden.-print0
ist etwas, das hilft, aber die gesamte Pipeline muss so etwas verwenden undsort
ist es auch nichtIch denke, die einfache Lösung ist:
quelle
Maximale Tiefe
Ich fand, dass es gut mit Jim Lewis 'Antwort funktioniert. Fügen Sie einfach ein bisschen wie folgt hinzu:
Sortierung
Wenn Sie in Sortierreihenfolge ausführen möchten, ändern Sie es wie folgt:
Dies wird nur als Beispiel in der folgenden Reihenfolge ausgeführt:
Unbegrenzte Tiefe
Wenn Sie unter bestimmten Bedingungen in unbegrenzter Tiefe ausführen möchten, können Sie Folgendes verwenden:
Fügen Sie dann wie folgt über jede Datei in den untergeordneten Verzeichnissen ein:
und irgendwo im Hauptteil der übergeordneten Datei:
quelle