Ich würde gerne laufen:
./a.out < x.dat > x.ans
für jeden * .dat - Datei im Verzeichnis A .
Sicher, es könnte durch Bash / Python / was auch immer Skript getan werden, aber ich schreibe gerne sexy Einzeiler. Alles was ich erreichen konnte ist (immer noch ohne Standard):
ls A/*.dat | xargs -I file -a file ./a.out
Aber -a in xargs versteht replace-str 'file' nicht.
Danke für die Hilfe.
io-redirection
xargs
Nikolay Vyahhi
quelle
quelle
Antworten:
Zunächst einmal nicht verwendet
ls
Ausgabe als Dateiliste . Verwenden Sie die Shell-Erweiterung oderfind
. Nachfolgend finden Sie mögliche Folgen des Missbrauchs von ls + xargs und ein Beispiel für die ordnungsgemäßexargs
Verwendung.1. Einfacher Weg: for loop
Wenn Sie nur die Dateien unter verarbeiten möchten, sollte
A/
eine einfachefor
Schleife ausreichen:2. pre1 Warum nicht
ls | xargs
?Hier ist ein Beispiel dafür , wie schlecht die Dinge, wenn Sie verwenden
ls
mitxargs
für den Job. Stellen Sie sich folgendes Szenario vor:Lassen Sie uns zuerst einige leere Dateien erstellen:
siehe die Dateien und dass sie nichts enthalten:
Führe einen magischen Befehl aus mit
xargs
:das Ergebnis:
Sie haben es also gerade geschafft, beide
mypreciousfile.dat
und zu überschreibenmypreciousfile.dat.ans
. Wenn sich Inhalte in diesen Dateien befunden hätten, wären sie gelöscht worden.2. Verwenden
xargs
: den richtigen Weg mitfind
Wenn Sie darauf bestehen möchten
xargs
, verwenden Sie-0
(nullterminierte Namen):Beachten Sie zwei Dinge:
.dat.ans
Endung."
) enthält.Beide Probleme können auf unterschiedliche Weise durch Aufrufen der Shell gelöst werden:
3. Alles innerhalb erledigt
find ... -exec
Dies erzeugt wiederum
.dat.ans
Dateien und bricht ab, wenn Dateinamen enthalten"
. Verwendenbash
und ändern Sie dazu die Art und Weise, wie es aufgerufen wird:quelle
zsh
es als Shell verwendet wird (und SH_WORD_SPLIT nicht gesetzt ist), alle bösen Sonderfälle (Leerzeichen, "im Dateinamen usw.) nicht berücksichtigt werden müssen. Das Trivialefor file in A/*.dat; do ./a.out < $file > ${file%.dat}.ans ; done
funktioniert in allen Fällen.find
.Versuchen Sie Folgendes (die Syntax kann je nach verwendeter Shell etwas variieren):
$ for i in $(find A/ -name \*.dat); do ./a.out < ${i} > ${i%.dat}.ans; done
quelle
somefile.dat.dat
und alle Ausgaben in eine einzige Datei umzuleiten.somefile.dat.ans
Ausgabe-Zeug würde nicht so schön aussehen.-type file
wäre nett (kann nicht< directory
), und das macht die Ungewöhnlich-Dateiname-Fee traurig.Für einfache Muster ist die for-Schleife geeignet:
Für komplexere Fälle, in denen Sie ein anderes Hilfsprogramm zum Auflisten der Dateien benötigen (zsh oder bash 4 verfügen über ausreichend leistungsfähige Muster, die Sie selten finden müssen. Wenn Sie jedoch in der POSIX-Shell bleiben oder eine schnelle Shell wie dash verwenden möchten, müssen Sie für alles eine Suche durchführen nicht trivial), während lesen am besten geeignet ist:
Dies behandelt Leerzeichen, da das Lesen (standardmäßig) zeilenorientiert ist. Zeilenumbrüche und umgekehrte Schrägstriche werden nicht behandelt, da standardmäßig Escape-Sequenzen interpretiert werden (mit denen Sie zwar eine neue Zeile übergeben können, aber find dieses Format nicht generieren kann). Viele Shells haben die
-0
Möglichkeit zu lesen, so dass Sie mit allen Zeichen umgehen können, aber leider ist es kein POSIX.quelle
Verwenden Sie GNU Parallel:
Zusätzlicher Bonus: Sie erledigen die Bearbeitung parallel.
Sehen Sie sich die Intro-Videos an, um mehr zu erfahren: http://www.youtube.com/watch?v=OpaiGYxkSuQ
quelle
Ich denke, Sie brauchen mindestens einen Shell-Aufruf in den Xargs:
Bearbeiten: Es sollte beachtet werden, dass dieser Ansatz nicht funktioniert, wenn die Dateinamen Leerzeichen enthalten. Kann nicht arbeiten Selbst wenn Sie find -0 und xargs -0 verwenden, damit xargs die Leerzeichen richtig versteht, wird der Shell-Aufruf -c sie quaken. Das OP hat jedoch ausdrücklich nach einer xargs-Lösung gefragt, und dies ist die beste xargs-Lösung, die ich mir ausgedacht habe. Wenn Leerzeichen in Dateinamen ein Problem sein könnten, verwenden Sie find -exec oder eine Shell-Schleife.
quelle
ls
Ausgabe zu analysieren .ls
gibt Dinge wie Leerzeichen aus, ohne zu entkommen, und das ist das Problem.ls
ist nicht gut. Aberxargs
kann sicher mit find verwendet werden - siehe den Vorschlag No 2 in meiner Antwort.Es besteht keine Notwendigkeit, es zu komplizieren. Du könntest es mit einer
for
Schleife machen:Das
${file%.dat}.ans
Bit entfernt das.dat
Dateinamensuffix aus dem Dateinamen$file
und fügt.ans
es stattdessen an das Ende an.quelle