Różnica między „xargs” a zastępowaniem poleceń?

14

W wielu przypadkach używam podstawiania poleceń zamiast xargs. Na przykład rm $(ls)jest taki sam jakls | xargs rm

Jakie naprawdę są między nimi różnice?

Myślę, że jedną z różnic jest to, że podstawianie poleceń działa w podpowłoce, podczas gdy xargsdziała w bieżącej powłoce, ale nie jestem pewien.

Proszę wymienić różnice.

Sinoosh
źródło

Odpowiedzi:

9

Jedną różnicą jest to, że w przypadku zastąpienia komendy zamiast potoku rozmiar przekazywanych danych jest ograniczony przez rozmiar bufora komend, dlatego w niektórych przypadkach jest on obcinany bez ostrzeżenia. Oznacza to również, że całe wyjście polecenia musi zostać wygenerowane i zapisane w pamięci, zanim zostanie przekazane do następnego polecenia, więc w przypadku dużych wyjść można użyć znacznie więcej pamięci, niż to konieczne.

Innym problemem związanym z pierwszą metodą jest to, że dane wyjściowe są dzielone na białe znaki, więc nie można obsługiwać nazw plików ze spacjami. xargsma również wpływ problem z białymi znakami, ale można to naprawić, zmieniając używany separator. Nawiasem mówiąc, aby poprawnie obsługiwać nazwy plików, w drugim przykładzie należy użyć bajtu zerowego jako separatora.

Trzeci problem polega na tym, że globusy są rozwinięte, więc jeśli plik ma gwiazdki lub znaki zapytania w swojej nazwie, nieoczekiwane wyniki.

Miłą dyskusję na ten temat można znaleźć tutaj: http://mywiki.wooledge.org/ParsingLs

Prawidłowa składnia to

echo rm *

lub jeśli musisz użyć xargs,

find . -maxdepth 1 -print0 | xargs -0 echo rm

Usuń, echogdy wynik wygląda poprawnie.

użytkownik000001
źródło
1
@Sinoosh: xargsdziała również w podpowłoce z powodu potoku, chyba że włączysz shopt -s lastpipe, w którym to przypadku będzie działał w bieżącej powłoce. Nie sądzę jednak, aby działanie w podpowłoce stanowiło problem w tym przypadku, ponieważ nie zmieniasz żadnych zmiennych.
user000001
1
@Sinoosh: Aby przekazywać argumenty jeden po drugim, możesz użyć -lflagi, np find . -maxdepth 1 -print0 | xargs -0 -l rm. W przypadku drugiego pytania nie można używać lsz, xargs -0ponieważ ls nie dzieli wyniku na butlę zerową, ale z
znakami
1
@Sinoosh: Nie pierwszy akapit, ale drugi: xargs bez -0opcji cierpi z powodu białych znaków.
user000001
1
Czytaj man xargs, używaj echodo testowania, nie rm. xargspozwala nam przekroczyć limity powłoki (część bufora jest ograniczona do 65 KB, lista nazw plików nie jest).
waltinator
1
@Sinoosh: Nie mam dobrego podręcznego podręcznika, ale możesz pisać, xargs --show-limitsa zobaczysz limit ustawiony w systemie,
user000001