Załóżmy, że chcę usunąć wszystkie pliki z katalogu oprócz jednego o nazwie „notes.txt”. Chciałbym to zrobić z rurociągu ls | grep -v "notes.txt" | xargs rm
. Dlaczego potrzebuję xargs, jeśli wyjście drugiego potoku jest wejściem, którego powinien używać rm?
Dla porównania potok echo "#include <knowledge.h>" | cat > foo.c
wstawia echo tekstu do pliku bez użycia xargs. Jaka jest różnica między tymi dwoma rurociągami?
ls | grep -v "notes.txt" | xargs rm
do usuwania wszystkiego oprócznotes.txt
, lub ogólnie, nigdy nie analizowaćls
danych wyjściowych . Twoje polecenie przestanie działać, jeśli na przykład pojedynczy plik zawiera spację. Bezpieczniej byłobyrm !(notes.txt)
w Bash (zshopt -s extglob
setem) lubrm ^notes.txt
w Zsh (zEXTENDED_GLOB
) itp.find . -maxdepth 1 -mindepth 1 -print0 | xargs -0
zamiastls | xargs
:-)Odpowiedzi:
Mylisz dwa bardzo różne rodzaje danych wejściowych: STDIN i argumenty. Argumenty to lista ciągów znaków przekazywanych do komendy na początku, zwykle poprzez podanie ich po nazwie komendy (np.
echo these are some arguments
Lubrm file1 file2
). Z drugiej strony STDIN jest strumieniem bajtów (czasem tekstowym, a czasem nie), które polecenie (opcjonalnie) może odczytać po uruchomieniu. Oto kilka przykładów (uwaga, któracat
może przyjmować argumenty lub STDIN, ale robi z nimi różne rzeczy):xargs
można uznać za konwersję danych wejściowych w stylu STDIN na argumenty:echo
faktycznie robi mniej więcej odwrotnie: konwertuje swoje argumenty na STDOUT (który może być potokowany do STDIN innej komendy):źródło
cat
pobiera dane wejściowe odSTDIN
irm
nie. W przypadku takich poleceń należyxargs
iterowaćSTDIN
wiersz po wierszu i wykonywać polecenia z parametrami wiersza polecenia.źródło