|
|
(13 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) |
Zeile 6: |
Zeile 6: |
| * Wenn dies nicht möglich sein sollte oder sich eine Dateiliste nicht mit Wildcards erstellen lässt, kann man das Kommando xargs verwenden. | | * Wenn dies nicht möglich sein sollte oder sich eine Dateiliste nicht mit Wildcards erstellen lässt, kann man das Kommando xargs verwenden. |
| * Wenn viele Dateien (manchmal über den Verzeichnisbaum verteilt) gleichartig behandeln werden sollen, ob die Dateien nun gelöscht, der Eigentümer oder die Zugriffsrechte geändert werden soll, ist ''find(1)'' eine gute Lösung | | * Wenn viele Dateien (manchmal über den Verzeichnisbaum verteilt) gleichartig behandeln werden sollen, ob die Dateien nun gelöscht, der Eigentümer oder die Zugriffsrechte geändert werden soll, ist ''find(1)'' eine gute Lösung |
| <syntaxhighlight lang="bash" highlight="1" line> | | <syntaxhighlight lang="bash" highlight="1" line copy> |
| find / -user toelpel -exec rm \{\} \; | | find / -user toelpel -exec rm \{\} \; |
| </syntaxhighlight> | | </syntaxhighlight> |
Zeile 16: |
Zeile 16: |
|
| |
|
| == Installation == | | == Installation == |
| <syntaxhighlight lang="bash" highlight="1" line>
| | ''xargs'' ist Teil des Pakets [[findutils]] |
|
| |
|
| </syntaxhighlight>
| |
| == Aufruf == | | == Aufruf == |
| <syntaxhighlight lang="bash" highlight="1" line> | | <syntaxhighlight lang="bash" highlight="1" line copy> |
| xargs [options] [command [initial-arguments]] | | xargs [options] [command [initial-arguments]] |
| </syntaxhighlight> | | </syntaxhighlight> |
Zeile 29: |
Zeile 28: |
|
| |
|
| ''xargs(1)'' hat die Funktion Kommandozeilen aus Standard-Input zu erstellen und auszuführen. | | ''xargs(1)'' hat die Funktion Kommandozeilen aus Standard-Input zu erstellen und auszuführen. |
| <syntaxhighlight lang="bash" highlight="1" line> | | <syntaxhighlight lang="bash" highlight="1" line copy> |
| find / -user toelpel -print | xargs rm | | find / -user toelpel -print | xargs rm |
| </syntaxhighlight> | | </syntaxhighlight> |
Zeile 71: |
Zeile 70: |
| |} | | |} |
|
| |
|
| === Parameter === | | === Argumente === |
| === Umgebungsvariablen === | | === Umgebungsvariablen === |
| === Exit-Status === | | === Exit-Status === |
|
| |
| == Anwendung ==
| |
| === Dateinamen mit Leerzeichen ===
| |
| Üblicher Weise enthält der IFS das Leerzeichen, daher bricht ''xargs ''die Dateinamen dort auseinander.
| |
| * Dem ist abzuhelfen, wenn man die GNU-Version der benutzten Tools (find und xargs) verwendet.
| |
| * ''find(1)'' gibt man bekannt, er möge mit ASCII-NUL beendete Zeichenketten ausgeben, und xargs, er möge solche erwarten:
| |
| find / -user toelpel -print0 | xargs -0 rm
| |
|
| |
| === Eingabedatei als Parameter ===
| |
| Sollen die Dateien verschoben werden, erwartet mv die Quelldateien als erstes, das Zielverzeichnis als letztes Argument.
| |
| * Dieses Problem löst man bei ''xargs(1)'' genauso wie bei
| |
|
| |
| <syntaxhighlight lang="bash" highlight="1" line>
| |
| find / -user toelpel -print0 | xargs -0 mv {} /tmp/toelpel-trash
| |
| </syntaxhighlight>
| |
|
| |
| Die Zeichenkombination "{}" zeigt dem ''xargs(1)'', an welcher Stelle er die Argumentliste für das Kommando einzufügen hat.
| |
|
| |
| === Beispiele===
| |
| find /tmp -name core -type f -print | xargs /bin/rm -f
| |
| * Finde Dateien mit dem Namen core in oder unterhalb des Verzeichnisses /tmp und lösche diese.
| |
| * Achtung, diese Aktion schlägt fehl falls die Dateinamen Zeilenvorschübe, einfache oder doppelte Anführungszeichen oder Leerzeichen enthalten.
| |
| * Mit folgendem Befehl werden alle Dateien aus dem aktuellen Verzeichnis entfernt, die auf das Muster '''*.tmp</nowiki>''' passen.
| |
| * Dabei werden Dateien, deren Namen Leerzeichen enthalten ebenfalls berücksichtigt: find . -name "*.tmp" -print0 | xargs -0 rm
| |
| * Als nächstes eine Anwendung mit der Ersatz-Zeichenkette {}.
| |
| * Alle Dateien des Benutzers mit der uid 1001 werden nach '''/tmp/klaus/test''' verschoben.
| |
|
| |
| ; Achtung
| |
| * Die Verzeichnisstruktur wird dabei nicht wieder hergestellt.
| |
| * Die Dateien landen wirklich alle in '''/tmp/klaus/test'''.
| |
| find . -uid 1001 -print | xargs -i mv {} /tmp/klaus/test
| |
| * Wenn man eine Datei '''software.list''' mit den Namen von Paketen hat, die sich im Verzeichnis '''~/installation/''' befindet und die wie folgt aufgebaut ist alltray audacity avidemux azureus compizconfig-settings-manager
| |
| * kann man mit xargs -a ~/installation/software.list sudo apt-get install
| |
| * die Pakete komfortabel alle auf einmal installieren.
| |
| * Dabei werden bereits installierte Pakete übersprungen.
| |
| * Möchte man mehrere Dateien herunterladen, aber die Geschwindigkeit der Server lastet die eigene Internetverbindung nicht aus, so kann man mit xargs einfach mehrere Instanzen benutzen.
| |
| xargs -a downloadlist -n 1 -P 4 wget
| |
| * Dieser Befehl übergibt jeweils eine URL aus der Datei '''downloadlist''' an wget.
| |
| * Dabei wird wget vier mal jeweils mit einer anderen Datei gestartet.
| |
| * So werden vier Dateien auf einmal heruntergeladen und die Internetverbindung optimal ausgenutzt.
| |
|
| |
| === Weitere Möglichkeiten ===
| |
| This command is equivalent to using ''find'' with ''xargs'', only a bit shorter and more efficient.
| |
| * But this form of ''‑exec'' can be combined with a shell feature to solve the other problem (names with spaces).
| |
| * The POSIX shell allows us to use: sh -c '''command-line''' [ ''command-name'' [ ''args''... ] ]
| |
| * We don't usually care about the ''command-name'', so “X”, “dummy”, “”, or “'inline cmd'” is often used.
| |
| * Here's an example of efficiently copying found files to ''/tmp'', in a POSIX-compliant way.
| |
| find . -name '*.txt' -type f \ -exec sh -c 'exec cp -f "$@" /tmp' X '{}' +
| |
| * Obvious, simple, and readable, isn't it? Perhaps not, but worth knowing since it is safe, portable, and efficient.
| |
|
| |
| === Beispiel 1 ===
| |
| Wo in meinem Homeordner liegt die Datei "test.pdf"? find ~ -name test.pdf
| |
| * Ihr habt vor ein paar Minuten eilig etwas gespeichert, habt aber den Namen der Datei und den Pfad sofort vergessen.
| |
| * Irgendwo in eurem Homeordner, irgendein Name, vor ein paar Minuten...
| |
| find ~ -type f ! -path '*/.*' -mmin -10 -ls
| |
| * Die Optionen im Einzelnen:* ~ -- rekursiv in meinem Homeordner
| |
| * -type f -- eine Datei (kein Ordner...)
| |
| * ! -path '*/.*' -- ohne Dateien oder Ordner, die mit Punkt beginnen.
| |
| * -mmin -10 -- nicht älter als 10 Minuten
| |
| * -ls -- lange Anzeige (wie ls -l)
| |
| * Variante: mit Dotfiles, nicht aber Ordner, die mit Punkt beginnen (also ohne .gnome/ oder .kde/ und so weiter, aber mit .bash_history).
| |
| * Und zwar alle Dateien, die nicht älter als zwei Tage sind.
| |
| find ~ ! -path '*/.*/*' -type f -ctime -2
| |
| * Im Homeordner alle Dateien finden, deren Namen Leerzeichen enthalten.
| |
| * Wieder ohne Dateien oder Ordner, die mit Punkt beginnen.
| |
| find $HOME ! -path '*/.*' -type f -name '* *'
| |
| * $HOME -- ist gleichbedeutend mit ~ * -name '* *' -- Name enthält mindestens ein Leerzeichen
| |
| * Ganz ähnlich, aber diesmal wird nach Ordnern gesucht: find $HOME ! -path '*/.*' -type d -name '* *' -type d -- Ordner (type directory)
| |
| * Im Ordner public_html alle HTML und PHP Dateien ausfindig machen, in denen ".mp3" erwähnt wird.
| |
| * Nur die Dateinamen ausgeben.
| |
| find ~/public_html \( -name \*.html -o -name \*.php \) | xargs grep -l '.mp3'
| |
| * Zu beachten: ( ) * müssen vor der Bash versteckt, also mit Backslash escaped werden.
| |
| * Andere Methode (-exec statt xargs), gleiches Ergebnis.
| |
| find ~/public_html \( -name \*.html -o -name \*.php \) -exec grep -l '.mp3' '{}' \+
| |
| * Zu beachten: -exec mit''' \+''' abschließen statt mit '''\; '''beschleunigt das Abarbeiten ungemein, weil dann mehrere grep Prozesse parallel gestartet werden (vgl. xargs).
| |
| * Setzt eine halbwegs aktuelle Version von find voraus.
| |
| * Hoppla, da sind auch Dateien mit Leerzeichen im Namen dabei? Kein Problem.
| |
| find ~/public_html \( -name \*.html -o -name \*.php \) -print0 | xargs -0 grep -l '.mp3'
| |
| * finds Option -print0 erzeugt die richtige Ausgabe für xargs Option -0
| |
| * Anderer Einsatzzweck: Plattenplatz wird knapp, wo sind die großen Dateien?
| |
| * Also zum Beispiel: in meinem Homeordner alle Dateien, die größer als 500MB sind.
| |
| find ~ -size +500M
| |
| * Alle Dateien/Ordner in meinem Homeordner finden, die nicht mir gehören: find ~ ! -user $( whoami ) -ls
| |
| * Alle Dateien/Ordner in meinem Homeordner, die root gehören: find ~ -user root
| |
| * Alle Dateien/Ordner in meinem Homeordner, die die Rechte auf 777 gesetzt haben,
| |
| * also Lese/Schreib/Ausführrechte für alle haben, lange Ausgabe wie "ls -l".
| |
| find ~ -perm 777 -ls
| |
| * Welche Art von Dateien (Mimetype) liegen im Ordner Documents, mit Rücksicht auf Dateien mit Leerzeichen im Namen, nur in diesem Ordner, keine Unterordner: find ~/Documents/ -maxdepth 1 -type f -print0 | xargs -0 file
| |
| * Find sucht immer rekursiv, es sei denn, man schränkt mit "-maxdepth" die Tiefe ein.
| |
| * Die Liste ließe sich beliebig fortsetzen.
| |
| * Wie vielseitig find ist, zeigt sich schon an der Länge der manpage.
| |
| * Find findet nach Name, Regular expression, Größe, Datum, Dateityp,...
| |
| * und so weiter und läßt sich mit "-exec" und der Pipe für "xargs" zu beinahe allem verwenden, was nur auf bestimmte Dateien/Ordner angewandt werden soll.
| |
| * Darum wird das Kommando in vielen Shellskripten verwendet.
| |
|
| |
| === Beispiel 2 ===
| |
| Dateien im aktuellen Ordner und Unterordnern finden, deren Namen einem bestimmen Muster entsprechen:
| |
| find . -name "*.jpg"
| |
| * Dateien finden, deren Namen nicht einem bestimmten Muster entsprechen:
| |
| find . \! -name "*.jpg"
| |
| * Dateien finden, deren Namen einem bestimmten Muster entsprechen und die einen bestimmten Text enthalten:
| |
| find . -name "*.php" -exec grep -il "suchtext" {} \;
| |
| * Dateien finden, die bestimmte Datei-Endungen haben (Mit Regular-Expressions finden):
| |
| find . -regex ".*(php|html|tpl)$"
| |
| * Große Dateien finden (Dateien finden, die größer als ca. 500 MB sind):
| |
| find . -type f -size +500000k -exec ls -lh {} \;
| |
| * Dateien finden, deren Pfade einem bestimmten Pattern entsprechen:
| |
| find . -path "*/.svn*"
| |
| * Dateien finden, deren Pfade nicht einem bestimmten Pattern entsprechen:
| |
| find . \! -path "*/.svn*"
| |
| * Dateien finden, die nicht einem bestimmten User (nicht root) gehören:
| |
| find . \! -user root
| |
| * Dateien finden, die “oo” oder “ee” im Namen haben:
| |
| find . \( -name "*oo*" -or -name "*ee*" \)
| |
| * Dateien finden, die nicht “oo” oder “ee” im Namen haben:
| |
| find . \! \( -name "*oo*" -or -name "*ee*" \)
| |
| * Geht nicht mit find (GNU findutils) 4.4.2: '''
| |
| find . -regex “.*(php|html|tpl)$”''' mkdir /tmp/tst cd /tmp/tst mkdir -p 1/2/3 mkdir -p 4/5/6 touch la.php touch 1/2/uu.tpl touch 4/lala.html touch 4/5/6/eee.php touch 4/5/oooooo' find . -regex “.*(php|html|tpl)$”
| |
| * es wird nix ausgegeben :(
| |
|
| |
| === Beispiel 3 ===
| |
| Angenommen, Sie möchten eine Liste der Verzeichnisse in ''/usr/share'' erhalten, dann tippen Sie: find /usr/share -type d
| |
| * Angenommen, Sie haben einen HTTP-Server und alle Ihre HTML-Dateien befinden sich in ''/home/httpd/html'', wo Sie sich auch gerade befinden.
| |
| * Sie möchten eine Liste aller Dateien, deren Inhalt seit einem Monat nicht verändert worden ist.
| |
| * Da die Seiten von verschiedenen Schreibern stammen, enden einige auf ''html'' und einige auf ''htm''.
| |
| * Sie möchten diese Dateien in das Verzeichnis ''/home/httpd/obsolete'' verknüpfen.
| |
| * Geben Sie folgendes ein:[http://www.murnauer.de/mandrakeref/command-find.html#FTN.AEN4397 []
| |
|
| |
| * Denken Sie daran, dass in diesem Beispiel beide Verzeichnisse auf dem selben Dateisystem sein müssen!
| |
| find \( -name "*.htm" -o -name "*.html" \) -a -ctime -30 -exec ln {} /home/httpd/obsolete \;
| |
| * Gut, das hier ist etwas komplex und verlangt nach Erklärung.
| |
| * Das Suchkriterium ist Folgendes: \( -name "*.htm" -o -name "*.html" \) -a -ctime -30
| |
| * Es findet alle Dateien, die entweder auf ''.htm'' oder auf ''.html'' enden (''( -name "*.htm" -o -name "*.html" )'') und (''-a'') die in den letzten 30 Tagen nicht modifiziert wurden (''-ctime -30'').
| |
| * Beachten Sie die Klammern, die hier notwendig sind, da ''-a'' eine höhere Wertigkeit hat.
| |
| * Ließen Sie sie weg, würde das Kommando alle Dateien mit der Endung ''.htm'' finden sowie die Dateien, die auf ''.html'' enden und seit einem Monat nicht modifiziert wurden.
| |
| * Beachten Sie auch, dass die Klammern vor der Shell geschützt wurden.
| |
| * Gäben Sie ''( .. )'' anstelle von ''\( .. \)'' ein, würde die Shell versuchen, diese zu interpretieren und das Kommando ''-name "*.htm" -o -name "*.html"'' in einer Sub-Shell auszuführen.
| |
| * Sie können diesen Schutz übrigens auch durch Anführungszeichen erreichen.
| |
| * Und schließlich das Kommando, das für jede gefundene Datei ausgeführt wird: -exec ln {} /home/httpd/obsolete \;
| |
| * Auch hier müssen Sie das '';</nowiki>'' vor der Shell schützen, da diese es sonst als Kommandoseparator interpretiert und find sich beschweren wird, dass ''-exec'' ein Argument fehlt.
| |
| * Ein letztes Beispiel:
| |
| * Sie haben ein großes Verzeichnis mit allen möglichen Bilddateien: ''/shared/images''.
| |
| * Normalerweise benutzen Sie touch, um den Zeitstempel einer Datei namens ''stamp'' in diesem Verzeichnis aufzufrischen, um eine Zeitreferenz zu haben.
| |
| * Sie wollen eine Liste aller JPEG-Dateien, die jünger als die Datei ''stamp'' sind.
| |
| * Da Sie die Dateien von verschiedenen Quellen haben, haben Sie die Endungen ''jpg'', ''jpeg'', ''JPG'' oder ''JPEG''.
| |
| * Sie möchten nicht im Verzeichnis ''old'' suchen, Sie möchten diese Liste zugeschickt bekommen und Ihr Benutzername ist ''john'':
| |
| find /shared/images -cnewer \ /shared/images/stamp \ -a -iregex ".*\.jpe?g" \ -a -not -regex ".*/old/.*" \ | mail john -s "Neue Images"
| |
| * Nun wäre es nicht sehr schön, dieses Kommando regelmäßig neu eingeben zu müssen, also brauchen Sie…?
| |
|
| |
| === Problembehebung ===
| |
|
| |
|
| == Konfiguration == | | == Konfiguration == |
Zeile 230: |
Zeile 79: |
| == Anhang == | | == Anhang == |
| === Siehe auch === | | === Siehe auch === |
| {{Special:PrefixIndex/{{BASEPAGENAME}}}} | | {{Special:PrefixIndex/{{BASEPAGENAME}}/}} |
| ==== Dokumentation ====
| | === Dokumentation === |
|
| |
|
| ===== Man-Page =====
| | ; Man-Page |
| # xargs(1) | | # xargs(1) |
|
| |
|
| ===== Info-Pages =====
| | ;Info-Page |
| ==== Links ====
| | === Links === |
| ===== Projekt =====
| | ==== Projekt ==== |
| ===== Weblinks =====
| | ==== Weblinks ==== |
|
| |
|
| {{DEFAULTSORT:xargs}} | | {{DEFAULTSORT:xargs}} |
Zeile 245: |
Zeile 94: |
|
| |
|
| [[Kategorie:Linux/Befehl]] | | [[Kategorie:Linux/Befehl]] |
| | [[Kategorie:findutils]] |
| </noinclude> | | </noinclude> |