2010-09-16 13:40:08 +0000 2010-09-16 13:40:08 +0000
88
88

Hoe pijp ik uitvoer van commando's naar andere commando's?

Voorbeeld:

ls | echo drukt niets af (een lege regel, eigenlijk). Ik zou verwachten dat het een lijst met bestanden zou afdrukken.

ls | grep 'foo', aan de andere kant, werkt zoals verwacht ( drukt bestanden af met ‘foo’ in hun naam).

Wat ik in deze situaties doe is zoiets als: ls | while read OUT; do echo $OUT; done maar dat is nogal omslachtig.

Waarom werkt piping met sommige commando’s wel, maar met andere niet? Hoe kan ik dit probleem omzeilen ?

Antwoorden (4)

123
123
123
2010-09-16 14:16:59 +0000

Er is een onderscheid tussen commandoregelargumenten en standaardinvoer. Een pipe verbindt standaarduitvoer van het ene proces met standaardinvoer van een ander. Dus

ls | echo

Verbindt standaarduitvoer van ls met standaardinvoer van echo. Prima, toch? Nou, echo negeert de standaard invoer en dumpt zijn commandoregel argumenten - die er in dit geval geen zijn - naar zijn eigen stdout. De uitvoer: helemaal niets.

Er zijn een paar oplossingen in dit geval. Eén is om een commando te gebruiken dat stdin leest en dumpt naar stdout, zoals cat.

ls | cat

Zal ‘werken’, afhankelijk van wat je definitie van werken is.

Maar hoe zit het in het algemene geval. Wat je echt wilt is stdout van een commando converteren naar command line args van een ander commando. Zoals anderen al hebben gezegd, is xargs in dit geval het canonieke hulpprogramma, dat de commandoregelargumenten voor een commando uit zijn stdin leest, en commando’s samenstelt om uit te voeren.

ls | xargs echo

Je zou dit ook wat kunnen omzetten, met het substitutie commando $()

echo $(ls)

Zou ook doen wat je wilt.

Beide tools zijn de kern van shell scripting, je zou ze allebei moeten leren.

Voor de volledigheid, zoals je in de vraag aangeeft, de andere basismanier om stdin om te zetten in commandoregel args is het ingebouwde read commando van de shell. Het converteert “words” (woorden zoals gedefinieerd door de IFS variabele) naar een temp variabele, die je kunt gebruiken in elke commandorun.

19
19
19
2010-09-16 13:54:37 +0000

ls | echo drukt alleen een lege regel af omdat echo geen invoer leest; het laatste commando van de pijplijn is eigenlijk echo dat niets anders dan een lege regel afdrukt.

In het algemeen:

a | b

zorgt ervoor dat de uitvoer van a de invoer van b wordt. Ik stel voor dat je de Pipelines sectie van man bash leest.


Als je echt ls en echo samen wilt gebruiken volgen hier wat (tamelijk nutteloze) voorbeelden:

ls | xargs -L 1 echo
echo `ls`
for i in `ls` ; do echo $i ; done
13
13
13
2010-09-16 14:03:04 +0000

Als je het echo commando wilt aanroepen, probeer dan:

ls | xargs echo

Dit zal ls aanroepen met de uitvoer van echo.

3
3
3
2011-11-09 09:48:27 +0000

Waarom niet gewoon gebruiken:

echo `ls`

Of veel veiliger:

echo "`ls -lrt`"