Verwenden von Daten, die nicht aus einer Datei, sondern aus einer Pipe in Befehlsoptionen gelesen wurden


18

Per man-Definition erhält dieser Befehl die Eingabe aus einer Datei.

$ command -r FILENAME

Angenommen, es FILENAMEhandelt sich um eine Datei mit einer Liste von Dateinamen, wie sie mit generiert wurde ls > FILENAME.

Wie kann ich stattdessen den Befehl mit dem Ergebnis von lsdirekt füttern ? In meinem Kopf sollte so etwas möglich sein:

$ ls | command -r

Aber es ist nicht der Fall, die Ausgabe von lswird nicht als Argument gehakt. Ausgabe:

Usage: command -r FILENAME
error: -r option requires an argument

Wie kann ich den gewünschten Effekt erzielen?


Antworten:


31

Dies ist befehlsabhängig. Einige Befehle, die aus einer Datei lesen, gehen davon aus, dass es sich bei der Datei um eine reguläre Datei handelt, deren Größe im Voraus bekannt ist und die von jeder Position gelesen und zurückgespult werden kann. Dies ist unwahrscheinlich, wenn der Inhalt der Datei eine Liste von Dateinamen ist: Dann ist der Befehl wahrscheinlich mit einer Pipe zufrieden , die von Anfang bis Ende nacheinander gelesen wird. Es gibt verschiedene Möglichkeiten, Daten über eine Pipe an einen Befehl weiterzuleiten, der einen Dateinamen erwartet.

  • Viele Befehle werden -als spezielle Namen behandelt, dh sie werden von der Standardeingabe gelesen, anstatt eine Datei zu öffnen. Dies ist eine Konvention, keine Verpflichtung.

    ls | command -r -
  • Viele Unix-Varianten enthalten spezielle Dateien /dev, die die Standarddeskriptoren bezeichnen. Wenn /dev/stdinvorhanden, entspricht das Öffnen und Lesen der Datei dem Lesen der Standardeingabe. Ebenso, /dev/fd/0wenn es existiert.

    ls | command -r /dev/stdin
    ls | command -r /dev/fd/0
  • Wenn Ihre Shell ksh, bash oder zsh ist, können Sie die Shell mit der Zuweisung eines Dateideskriptors beauftragen. Der Hauptvorteil dieser Methode besteht darin, dass sie nicht an die Standardeingabe gebunden ist, sodass Sie die Standardeingabe für etwas anderes verwenden und sie mehrmals verwenden können.

    command -r <(ls)
  • Wenn der Befehl erwartet, dass der Name eine bestimmte Form hat (normalerweise eine bestimmte Erweiterung), können Sie versuchen, ihn mit einem symbolischen Link zu täuschen.

    ln -s /dev/fd/0 list.foo
    ls | command -r list.foo

    Oder Sie können eine Named Pipe verwenden.

    mkfifo list.foo
    ls >list.foo &
    command -r list.foo

Beachten Sie, dass das Generieren einer Liste von Dateien mit lsproblematisch ist, da lsdie Dateinamen in der Regel unleserlich werden, wenn sie nicht druckbare Zeichen enthalten. printf '%s\n' *ist zuverlässiger - es wird jedes Byte buchstäblich in Dateinamen gedruckt. Dateinamen, die Zeilenumbrüche enthalten, verursachen weiterhin Probleme. Dies ist jedoch unvermeidbar, wenn der Befehl eine Liste von Dateinamen erwartet, die durch Zeilenumbrüche getrennt sind.


+1 für die Aufzählung aller Möglichkeiten. Die IMO-Prozessersetzung ist die richtige Antwort auf diese Situation.
Glenn Jackman

7

Es sollte sein:

ls | xargs -n 1 command -r

Bearbeiten: für Namen mit Leerzeichen:

ls | xargs -d '\n' -n 1 command -r

Dies kann problematisch sein, wenn commanddavon ausgegangen wird, dass alle für die Befehlszeile erforderlichen Dateinamen gleichzeitig vorhanden sind. Einige Versionen von xargs geben jeweils commandeinige Dateinamen an (10, scheint mir). Sieht aus wie GNU XARGS gibt alles auf einmal.
Bruce Ediger

2

Die einzige zuverlässige Lösung, von der ich weiß, dass sie alle Dateinamen, einschließlich der mit einem Zeilenumbruch, verarbeiten kann, ist:

find . -maxdepth 1 -print0 | xargs -n 1 -0 command -r

Das einzige unzulässige Zeichen im Dateinamen ist in diesem Fall das Nullzeichen, das in Dateinamen ohnehin nicht zulässig ist.


1

Viele Befehle akzeptieren -als "Dateiname", was "Standardeingabe verwenden" bedeutet, aber diese Konvention ist alles andere als universell. Lesen Sie die Manpage.


1

Dies sollte für Ihren Zweck funktionieren: ls | command -r /dev/stdin

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.