Frage

Wie kann ich xargs den Befehl genau einmal ausgeführt für jede Zeile der Eingabe gegeben? Es ist das Standardverhalten zu Brocken ist die Linien und den Befehl einmal ausführen, mehrere Zeilen für jede Instanz übergeben.

  

http://en.wikipedia.org/wiki/Xargs :

     

finden / path -type f -print0 | xargs -0 rm

     

In diesem Beispiel finden speist den Eingang von xargs mit einer langen Liste von Dateinamen. xargs dann teilt diese Liste in Unterlisten und Anrufe rm einmal für jede Unterliste. Das ist effizienter als diese funktional äquivalente Version:

     

finden / path type f exec rm {} \;

ich weiß, dass die Suche nach dem „exec“ Flag hat. Ich bin nur ein illustratives Beispiel von einer anderen Ressource zu zitieren.

War es hilfreich?

Lösung

Im Folgenden wird nur funktionieren, wenn Sie Räume in Ihrer Eingabe nicht haben:

xargs -L 1
xargs --max-lines=1 # synonym for the -L option

von der man-Seite:

-L max-lines
          Use at most max-lines nonblank input lines per command line.
          Trailing blanks cause an input line to be logically continued  on
          the next input line.  Implies -x.

Andere Tipps

Es scheint mir, alle bestehenden Antworten auf dieser Seite falsch sind, einschließlich der eine als richtig gekennzeichnet. Das ergibt sich aus der Tatsache, dass die Frage ist mehrdeutig.

Zusammenfassung: Wenn Sie möchten, den Befehl auszuführen „genau einmal für jede Zeile der Eingabe gegeben“ vorbei die gesamte Zeile (ohne Newline) an den Befehl als a Argument, dann ist dies die beste UNIX-kompatible Art und Weise, es zu tun:

... | tr '\n' '\0' | xargs -0 -n1 ...

GNU xargs kann oder nicht nützliche Erweiterungen, die es Ihnen ermöglichen, mit tr weg zu tun, aber sie sind auf OS X und anderen UNIX-Systemen verfügbar.

Jetzt für die lange Erklärung ...


Es gibt zwei Probleme zu berücksichtigen, wenn xargs mit:

  1. Wie funktioniert es die Eingabe in „Argumente“ aufgespalten; und
  2. , wie viele Argumente des Kind Befehl zu einem Zeitpunkt, zu übergeben.

xargs Verhalten zu testen, brauchen wir ein Programm, das wie oft zeigt sie ausgeführt und mit wie vielen Argumente hat wird. Ich weiß nicht, ob es ein Standard-Dienstprogramm, das zu tun, aber wir können es ganz einfach in der Bash-Code:

#!/bin/bash
echo -n "-> "; for a in "$@"; do echo -n "\"$a\" "; done; echo

Angenommen, Sie es als show im aktuellen Verzeichnis speichern und ausführbar machen, ist hier, wie es funktioniert:

$ ./show one two 'three and four'
-> "one" "two" "three and four" 

Nun, wenn die ursprüngliche Frage ist wirklich über Punkt 2 oben (wie ich denke, es ist, nachdem es ein paar Mal über das Lese) und es ist wie dieses (Änderungen fett) zu lesen:

  

Wie kann ich xargs den Befehl genau einmal für jedes Argument der Eingabe gegeben ausführen? Sein Standardverhalten ist die Eingabe in Argumente chunk und führen Sie den Befehl so wenig wie möglich , vorbei an mehreren Argumente für jede Instanz.

dann ist die Antwort -n 1.

Lassen Sie uns xargs' Standardverhalten vergleichen, die die Eingabe um Leerzeichen teilt und ruft den Befehl als wenig wie möglich:

$ echo one two 'three and four' | xargs ./show 
-> "one" "two" "three" "and" "four" 

und sein Verhalten mit -n 1:

$ echo one two 'three and four' | xargs -n 1 ./show 
-> "one" 
-> "two" 
-> "three" 
-> "and" 
-> "four" 

Wenn auf der anderen Seite, die ursprüngliche Frage war um Punkt 1. Eingabe Splitting und es war wie folgt gelesen werden (hier viele Leute scheinen kommt der Fall zu denken, das ist, oder verwirrend sind die beiden Punkte):

  

Wie kann ich den Befehl xargs ausführen mit genau ein Argument für jede Zeile der Eingabe gegeben? Sein Standardverhalten Brocken ist die Zeilen um Leerzeichen .

dann ist die Antwort subtiler.

Man würde denken, dass -L 1 von Hilfe sein könnte, aber es stellt sich heraus, dass es nicht Argument Parsing nicht ändert. Er führt den Befehl nur einmal für jede Eingabezeile, mit so vielen Argumenten wie es gab an diesem Eingabezeile:

$ echo $'one\ntwo\nthree and four' | xargs -L 1 ./show 
-> "one" 
-> "two" 
-> "three" "and" "four" 

Nicht nur das, aber wenn eine Zeile mit Leerzeichen endet, es auf die nächste angefügt wird:

$ echo $'one \ntwo\nthree and four' | xargs -L 1 ./show 
-> "one" "two" 
-> "three" "and" "four" 

Natürlich ist -L nicht über die Art und Weise xargs Änderung der Eingabe in Argumente aufteilt.

Das einzige Argument, das so tut, in einer plattformübergreifenden Art und Weise (ohne GNU-Erweiterungen) ist -0, die das Eingangs rund NUL Bytes aufteilt.

Dann ist es nur eine Frage der Zeilenumbrüche NUL mit Hilfe von tr übersetzen:

$ echo $'one \ntwo\nthree and four' | tr '\n' '\0' | xargs -0 ./show 
-> "one " "two" "three and four" 

Jetzt das Argument Parsing sieht alles in Ordnung, einschließlich der nachfolgenden Leerzeichen.

Schließlich, wenn Sie diese Technik mit -n 1 kombinieren, erhalten Sie genau eine Befehlsausführung pro Eingabezeile, was Eingang Sie haben, die noch eine andere Art und Weise auf die ursprüngliche Frage zu sehen sein (möglicherweise die intuitive, da der Titel) :

$ echo $'one \ntwo\nthree and four' | tr '\n' '\0' | xargs -0 -n1 ./show 
-> "one " 
-> "two" 
-> "three and four" 

Wenn Sie den Befehl ausführen für alle Linie (d Ergebnis) von find kommen, was dann brauchen Sie das xargs für?

Versuchen:

find Pfad -type f -exec your-Befehl {} \;

, wo der wörtliche {} durch den Dateinamen ersetzt wird und die wörtliche \; für find muß zu wissen, dass der benutzerdefinierte Befehl endet dort.

EDIT:

(nach dem Bearbeiten Ihrer Frage zu klären, dass Sie über -exec wissen)

Von man xargs:

  

-L max-Linien
   Verwenden Sie höchstens max-Linien nicht leere Eingabezeilen pro Kommandozeile. Nachgestellte    Rohlinge verursacht eine Eingabezeile auf der nächsten Eingabezeile logisch fortgesetzt werden.    Impliziert -x.

Beachten Sie, dass Dateinamen in Rohlingen Endung Sie Probleme verursachen würden, wenn Sie xargs verwenden:

$ mkdir /tmp/bax; cd /tmp/bax
$ touch a\  b c\  c
$ find . -type f -print | xargs -L1 wc -l
0 ./c
0 ./c
0 total
0 ./b
wc: ./a: No such file or directory

Also, wenn Sie nicht über die -exec Option ist es egal, Sie besser nutzen -print0 und -0:

$ find . -type f -print0 | xargs -0L1 wc -l
0 ./c
0 ./c
0 ./b
0 ./a
  

Wie kann ich xargs den Befehl genau einmal ausgeführt für jede Zeile der Eingabe gegeben?

ich nicht mit -L 1 Antwort, weil es keine Dateien mit Leerzeichen in ihnen umgehen ist, die eine Schlüsselfunktion von find -print0 ist.

echo "file with space.txt" | xargs -L 1 ls
ls: file: No such file or directory
ls: space.txt: No such file or directory
ls: with: No such file or directory

Eine bessere Lösung ist tr zu verwenden Zeilenumbrüche zu konvertieren Zeichen auf null (\0) und dann das xargs -0 Argument verwenden.

echo "file with space.txt" | tr '\n' '\0' | xargs -0 ls
file with space.txt

Wenn Sie dann die Anzahl der Anrufe müssen begrenzen Sie das -n 1 Argument verwenden können, einen Aufruf an das Programm für jeden Eingang zu machen:

echo "file with space.txt" | tr '\n' '\0' | xargs -0 -n 1 ls

Dies erlaubt Ihnen auch die Ausgabe der Fund zu filtern vor die Pausen in Nullen umgewandelt wird.

find . -name \*.xml | grep -v /workspace/ | tr '\n' '\0' | xargs -0 tar -cf xml.tar

Eine andere Alternative ...

find /path -type f | while read ln; do echo "processing $ln"; done
find path -type f | xargs -L1 command 

ist alles, was Sie brauchen.

Diese beiden Möglichkeiten auch arbeiten, und wird für andere Befehle arbeiten, finden nicht verwenden!

xargs -I '{}' rm '{}'
xargs -i rm '{}'

Beispiel Anwendungsfall:

find . -name "*.pyc" | xargs -i rm '{}

werden alle pyc Dateien in diesem Verzeichnis löschen, auch wenn die pyc Dateien Leerzeichen enthalten.

Mit dem folgenden Befehl werden alle Dateien (Typ f) in /path finden und dann kopieren Sie sie cp in den aktuellen Ordner verwenden. Beachten Sie die Verwendung, wenn -I % ein Platzhalter Zeichen in der cp Befehlszeile angeben, so dass Argumente nach dem Dateinamen platziert werden.

find /path -type f -print0 | xargs -0 -I % cp % .

Getestet mit xargs (GNU findutils) 4.4.0

Sie können die Zeilenzahl begrenzen, oder Argumente (wenn es Räume zwischen den einzelnen Argumente sind) unter Verwendung der --max-Linien oder --max-args Flaggen sind.

  -L max-lines
         Use at most max-lines nonblank input lines per command line.  Trailing blanks cause an input line to be logically continued on the next  input
         line.  Implies -x.

  --max-lines[=max-lines], -l[max-lines]
         Synonym  for  the -L option.  Unlike -L, the max-lines argument is optional.  If max-args is not specified, it defaults to one.  The -l option
         is deprecated since the POSIX standard specifies -L instead.

  --max-args=max-args, -n max-args
         Use at most max-args arguments per command line.  Fewer than max-args arguments will be used if the size (see  the  -s  option)  is  exceeded,
         unless the -x option is given, in which case xargs will exit.

Es scheint, ich habe nicht genug Ruf haben einen Kommentar hinzufügen href="https://stackoverflow.com/a/28806991/5844631"> Tobia Antwort oben zu xargs der gleichen Art und Weise auf den Windows-Plattformen zu experimentieren.

Hier ist eine Windows-Batch-Datei, die die gleiche Sache wie Tobia schnell eine codierte „show“ Skript tut:

@echo off
REM
REM  cool trick of using "set" to echo without new line
REM  (from:  http://www.psteiner.com/2012/05/windows-batch-echo-without-new-line.html)
REM
if "%~1" == "" (
    exit /b
)

<nul set /p=Args:  "%~1"
shift

:start
if not "%~1" == "" (
    <nul set /p=, "%~1"
    shift
    goto start
)
echo.

@Draemon Antworten scheint richtig zu sein mit „-0“ sogar mit Platz in der Datei.

Ich habe versucht, die xargs Befehl und ich fand, dass „-0“ arbeitet perfekt mit „-L“. auch sind die Räume behandelt (wenn der Eingang null beendet wurde). Folgendes ist ein Beispiel:

#touch "file with space"
#touch "file1"
#touch "file2"

Im Folgenden werden die NULL-Werte geteilt und den Befehl für jedes Argument in der Liste ausführen:

 #find . -name 'file*' -print0 | xargs -0 -L1
./file with space
./file1
./file2

so -L1 wird das Argument auf jeder null beendet Zeichen ausgeführt werden, wenn verwendet mit „-0“. Um zu sehen, den Unterschied Versuch:

 #find . -name 'file*' -print0 | xargs -0 | xargs -L1
 ./file with space ./file1 ./file2

selbst wird dies einmal ausführen:

 #find . -name 'file*' -print0  | xargs -0  | xargs -0 -L1
./file with space ./file1 ./file2

Der Befehl wird ausgeführt, sobald als „-L“ aufgeteilt jetzt nicht auf null Byte. Sie müssen beide „-0“ und „L“ schaffen, zu arbeiten.

In Ihrem Beispiel der Punkt, der die Ausgabe von Fund xargs kochend ist, dass das Standardverhalten von -exec Option des Funds ist es, den Befehl einmal für jede gefundene Datei auszuführen. Wenn Sie finden, verwenden, und Sie wollen ihre Standardverhalten, dann ist die Antwort ist einfach -. Nicht xargs verwenden zu beginnen

Ausführen ant Aufgabe Rein alle auf jedem build.xml zu aktuellem oder Unterordner.

find . -name 'build.xml' -exec ant -f {} clean-all \;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top