Przekazywanie argumentu do wielu poleceń w jednym wierszu

10

Chciałbym móc uruchomić wiele poleceń w tym samym pliku w jednym wierszu. Obecnie to robię:

commandA file && commandB file && perl -ne '...' file

Mój instynkt podpowiada mi, że powinien istnieć sposób na podanie argumentu nazwy pliku tylko raz i przesłanie go do obu poleceń jednocześnie xargslub coś podobnego:

find file | xargs commandA && xargs commandB && xargs perl -ne '...'

Kiedy próbuję, uruchamiane jest tylko pierwsze polecenie. Jak mogę osiągnąć to, co chcę zrobić?

Zaid
źródło

Odpowiedzi:

12

Możesz dla tego zdefiniować zmienną lokalną:

f=file; commandA $f && commandB $f && ...

Można również wykonać wszystko bezwarunkowo (zastępując &&z ;) lub równolegle (w zastępstwie &&z &).

Alternatywnie możesz także użyć rozszerzenia historii powłoki, aby odwołać się do poprzednich argumentów:

commandA file && commandB !:1 && ...
maxschlepzig
źródło
Nie do końca to, co miałem na myśli, ale jest interesującą alternatywą.
Zaid,
Co jest nie tak z tą odpowiedzią?
Chris,
To jest naprawdę fajne! Czy istnieje sposób, aby nie zdefiniować nowej zmiennej?
użytkownik
@ użytkownik, dodałem alternatywę.
maxschlepzig
8

W przypadku powłok takich jak Bash, Korn i Z, które mają podstawianie procesów, możesz to zrobić:

find file | tee >(xargs commandA) >(xargs commandB) >(xargs perl -ne '...')
Wstrzymano do odwołania.
źródło
2

Możesz użyć xargs do zbudowania linii poleceń, np .:

echo file | xargs -i -- echo ls -l {}\; wc -l {}

Po prostu potokuj powyższe w bash, aby go uruchomić:

echo file | xargs -i -- echo ls -l {}\; wc -l {} | bash

Rozszerzając przykład na wszystkie pliki * .c w bieżącym katalogu (ucieczka przed ls tutaj, aby zapobiec podstawieniu aliasu powłoki):

\ls -1 *.c | xargs -i -- echo ls -l {}\; wc -l {} | bash
frielp
źródło
Wykorzystano to, aby uzyskać listę wszystkich plików zawartych w katalogach, w których nazwa jest jak „enums”: find . -name "*enums*" | xargs -i echo -e echo {}\; ls -lh {}\; echo -e '\n\n' | bash
Matt Lachman
1

Sam bym na to nie głosował. Jest to głupie i niebezpieczne, ale tylko w celu podania sposobów na zrobienie tego, są:

for cmd in "commandA" "commandB" "perl -ne '...'" ; do eval $cmd file ; done

frabjous
źródło