it-swarm.com.de

Wie ignoriere ich die xargs-Befehle, wenn die stdin-Eingabe leer ist?

Betrachten Sie diesen Befehl:

ls /mydir/*.txt | xargs chown root

Es ist beabsichtigt, die Besitzer aller Textdateien in mydir in root zu ändern

Das Problem ist, dass, wenn keine .txt-Dateien in mydir vorhanden sind, xargs einen Fehler ausgibt, der besagt, dass kein Pfad angegeben wurde. Dies ist ein harmloses Beispiel, da ein Fehler ausgegeben wird. In einigen Fällen, wie in dem Skript, das ich hier verwenden muss, wird jedoch davon ausgegangen, dass das aktuelle Verzeichnis ein leerer Pfad ist. Wenn ich also diesen Befehl von /home/tom/ aus ausführe, dann gibt es für ls /mydir/*.txt kein Ergebnis und alle Dateien unter /home/tom/ haben ihre Besitzer in root geändert.

Wie kann ich also ein leeres Ergebnis von xargs ignorieren lassen?

139
HyderA

Für GNU xargs können Sie die Option -r oder --no-run-if-empty verwenden:

--no-run-if-empty 
-r 
Wenn die Standardeingabe keine Nicht-Leerzeichen enthält, führen Sie den Befehl nicht aus. Normalerweise wird der Befehl einmal ausgeführt, auch wenn keine Eingabe erfolgt. Diese Option ist eine Erweiterung von GNU.

233
Sven Marnach

man xargs sagt --no-run-if-empty.

10
thiton

Benutzer von Nicht-GNU-xargs können -L <#lines>, -n <#args>, -i und -I <string> nutzen:

ls /empty_dir/ | xargs -n10 chown root # chown executed every 10 args or fewer
ls /empty_dir/ | xargs -L10 chown root # chown executed every 10 lines or fewer
ls /empty_dir/ | xargs -i cp {} {}.bak # every {} is replaced with the args from one input line
ls /empty_dir/ | xargs -I ARG cp ARG ARG.bak # like -i, with a user-specified placeholder

Denken Sie daran, dass xargs die Zeile in Leerzeichen aufteilt, aber Zitate und Escapezeichen verfügbar sind. RTFM für Details.

10
arielCo

In Bezug auf xargs können Sie -r wie vorgeschlagen verwenden, es wird jedoch nicht von BSD xargs unterstützt.

Als Problemumgehung können Sie beispielsweise eine zusätzliche temporäre Datei übergeben:

find /mydir -type f -name "*.txt" -print0 | xargs -0 chown root $(mktemp)

oder seine Umleitung in null (2> /dev/null) umleiten, z.

find /mydir -type f -name "*.txt" -print0 | xargs -0 chown root 2> /dev/null || true

Eine andere bessere Methode besteht darin, die gefundenen Dateien mithilfe der while-Schleife zu durchlaufen:

find /mydir -type f -name "*.txt" -print0 | while IFS= read -r -d '' file; do
  chown -v root "$file"
done

Siehe auch: Leere Ergebnisse für Xargs in Mac OS X ignorieren


Beachten Sie auch, dass Ihre Methode zum Ändern der Berechtigungen nicht großartig ist und davon abgeraten wird. Definitiv sollten Sie die Ausgabe des ls-Befehls nicht analysieren (siehe: Warum Sie die Ausgabe von ls nicht analysieren sollten). Insbesondere wenn Sie Ihren Befehl über Root ausführen, da Ihre Dateien aus Sonderzeichen bestehen können, die von der Shell interpretiert werden können, oder wenn die Datei ein Leerzeichen um / enthält, können die Ergebnisse schrecklich sein.

Daher sollten Sie Ihren Ansatz ändern und stattdessen den Befehl find verwenden, z.

find /mydir -type f -name "*.txt" -execdir chown root {} ';'
7
kenorb

Unter OSX: Bash-Neuimplementierung von xargs, die das -r-Argument behandelt, setzen Sie z. in $HOME/bin und füge es der PATH hinzu:

#!/bin/bash
stdin=$(cat <&0)
if [[ $1 == "-r" ]] || [[ $1 == "--no-run-if-empty" ]]
then
    # shift the arguments to get rid of the "-r" that is not valid on OSX
    shift
    # wc -l return some whitespaces, let's get rid of them with tr
    linecount=$(echo $stdin | grep -v "^$" | wc -l | tr -d '[:space:]') 
    if [ "x$linecount" = "x0" ]
    then
      exit 0
    fi
fi

# grep returns an error code for no matching lines, so only activate error checks from here
set -e
set -o pipefail
echo $stdin | /usr/bin/xargs [email protected]
2
rcomblen

Dies ist ein Verhalten von GNU xargs, das mit -r, --no-run-if-empty unterdrückt werden kann.

Die BSD-Variante von xargs weist dieses Verhalten standardmäßig auf, sodass -r nicht benötigt wird. Seit FreeBSD 7.1 (veröffentlicht im Januar 2009) wird aus Gründen der Kompatibilität ein -r-Argument akzeptiert (das nichts tut).

Ich persönlich bevorzuge Longopts in Skripten, aber da * BSD xargs keine Longopts verwendet, benutze einfach "-r" und xargs wird auf * BSD und auf Linux-Systemen dasselbe tun

xargs unter MacOS (derzeit MacOS Mojave) unterstützt das Argument "-r" leider nicht.

0
Mirko Steiner