Xargs

xargs – polecenie uniksowych i większości uniksopodobnych systemów operacyjnych, używane do budowania i wykonywania poleceń ze standardowego wejścia. Jądro Linuxa o wersji do 2.6.23 nie może pobierać dowolnie długiej listy argumentów[1], więc zadaniem xargs jest podzielenie jej na wystarczająco małe podlisty.

Na przykład polecenie:

 rm /path/*

lub

 rm `find /path -type f`

może spowodować błąd i wyświetlenie komunikatu: "Argument list too long" jeżeli w /path znajduje się zbyt wiele plików. Jednakże poniższa wersja (odpowiednik rm `find /path -type f`) nie powinna już sprawiać kłopotów:

 find /path -type f -print0 | xargs -0 rm

W tym przykładzie, find przesyła na wejście xargs długą listę nazw plików. Xargs dokonuje podziału na podlisty i dopiero wtedy wywołuje polecenie rm dla każdej z nich. To polecenie jest wydajniejsze niż gdybyśmy chcieli napisać:

 find /path -type f -exec rm '{}' \;

co spowoduje wywołanie rm dla każdego, pojedynczego pliku. Warto jednak zwrócić uwagę na to, że w nowszych wersjach find poniższy wariant wykonuje dokładnie to samo, co wersja z użyciem xargs:

 find /path -type f -exec rm '{}' +

xargs często wykazuje się takim samym działaniem, jak backquote, lecz jest on bardziej uniwersalny i okazuje się bezpieczniejszym gdy na wejściu pojawiają się znaki białe lub specjalne. Dobrze łączyć go z poleceniami zwracającymi długie listy plików, jak chociażby find, locate, czy grep. Musimy jednak pamiętać wtedy o parametrze -0, jako że bez niego xargs nie radzi sobie najlepiej z nazwami zawierającymi ', " i spacje.

Przykłady

 find . -name "*.foo" | xargs grep bar

Równoznaczne z:

 grep bar `find . -name "*.foo"`

Zauważ, że powyższa komenda korzysta z odwróconych apostrofów (`) zamiast zwykłych ('). Jej zadaniem jest odnalezienie wszystkich plików o rozszerzeniu .foo, zawierających słowo bar, położonych w bieżącym folderze oraz w jego podkatalogach. Żadne z tych poleceń nie zadziała, jeżeli wśród nazw plików znajdują się białe znaki. Możemy rozwiązać ten problem wpisując:

 find . -name "*.foo" -print0 | xargs -0 grep bar

W ten sposób możemy wyodrębnić nazwy plików, rozwiązując tym samym problem z białymi znakami;

 find . -name "*.foo" -print0 | xargs -0 -t -r vi

Polecenie to przypomina poprzednie, jednakowoż uruchamia ono edytor vi dla każdego z plików. Flaga -t powoduje wypisanie komendy do strumienia stderr przed przystąpieniem do jej realizacji. -r jest rozszerzeniem GNU informującym, że xargs nie wykona polecenia jeżeli nie otrzyma nic na wejście.

 find . -name "*.foo" -print0 | xargs -0 -I {} mv {} /tmp/trash

Powyższa komenda korzysta z -I aby rozkazać xargs wypełnienie {} listą argumentów. Pamiętaj jednak, że nie wszystkie wersje xargs wspomagają składnię {}. W takim wypadku możesz napisać np:

 find . -name "*.foo" -print0 | xargs -0 -I xxx mv xxx /tmp/trash

Powyższe polecenie wykorzystuje xxx zamiast {} jako znacznik listy argumentów.

 find . -maxdepth 1 -type f -name "*.ogg" -print0 | xargs -0 -r cp -v -p --target-directory=/home/media

To polecenie to nic innego jak:

 cp -v -p *.ogg /home/media

lecz nie zajmuje ono tak wielu zasobów, kosztem niezwracania błędu kiedy polecenie cp otrzyma więcej plików niż może obsłużyć. Innym sposobem (w którym to sami decydujemy, gdzie umieścimy argumenty) to:

 find . -maxdepth 1 -type f -name "*.ogg" -print0 | xargs -0 -IMYFILES cp MYFILES /home/media

Znak -I w powyższej linii poleceń informuje xargs o tym z którego słowa zastępczego chcesz skorzystać (w przeciwnym wypadku doda argumenty na końcu komendy). Oprócz tego możesz użyć atrybutu -L w celu ograniczenia liczby argumentów. Wtedy polecenie będzie uruchamiane ponownie, aż do wyczerpania listy argumentów. Zaś użycie -L1 spowoduje uruchomienie programu tylko raz dla każdego z zadanych argumentów.

Problem separatorów

Wiele uniksowych narzędzi jest zorientowanych liniowo. Będą one więc działać z xargs tak długo, jak linie nie zawierają ', " lub spacji. Część uniksowych narzędzi może użyć znaku NUL jako separatora (np. perl (wymaga -0 i \0 zamiast \n), locate (wymaga użycia -0), find (wymaga użycia -print0), grep (potrzebuje -z lub -Z), sort (wymaga użycia -z)). Umieszczenie -0 po xargs rozwiązuje problem, lecz wiele innych narzędzi nie może używać znaku NUL jako separatora, np. head, tail, ls, echo, sed, tar, wc, which.

Ludzie często o tym zapominają i uznają, że xargs jest także zorientowany liniowo[2].

Poniżej zilustrowano problem separatorów:

 touch 'wazny_plik'
 touch 'mniej wazny_plik'
 ls mniej* | xargs rm
 mkdir -p '12" records'
 ls | xargs rmdir

Wykonanie poleceń spowoduje usunięcie wazny_plik i pozostawi katalog 12" records oraz plik o nazwie mniej wazny_plik nietknięte.

GNU Parallel jest zorientowanym liniowo odpowiednikiem Xargs, co umożliwia wykonanie powyższych zadań przy jego pomocy[3].

Przypisy

Linki zewnętrzne

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.
Kembali kehalaman sebelumnya