Naredbe za koje (možda) niste znali 17: xargs

Naredba "xargs" je jedna od onih za koju nikad niste čuli i nikad je niste rabili, ili je rabite stalno i to bez razmišljanja o dodatnim opcijama i mogućnostima. Ukratko, naredba xargs izvršava izlaz druge naredbe na način na koji vam to trenutno odgovara. Sličnu funkciju ima opcija "-exec" naredbe find, ali xargs je daleko fleksibilniji i jednostavniji za uporabu od često predugačkih konstrukcija naredbe find.

Naredbu xargs možete rabiti uz bilo koju naredbu koja ispisuje nešto na standardni izlaz, no najčešće se rabi baš uz naredbu find.

O naredbi find smo već napisali članak na adresi http://sistemac.carnet.hr/node/640, a sve što smo tamo opisali možete povezati s xargs i učiniti s tim datotekama što vam u tom trenutku treba (kopirati ih, prebaciti, obrisati...).

Osnovna i najčešća uporaba je neka jednostavna operacija nad nekim skupom datoteka:

$ ls *.jpg | xargs rm

ili

$ find . -maxdepth 1 -name \*.jpg | xargs rm

Ovakva će kombinacija naredbi obrisati sve slike iz tekućeg direktorija. Zašto nismo upotrijebili jednostavno "rm *.jpg"? Ukoliko slika ima jako puno (tisuće), može se pojaviti greška "Argument list too long". Iako je ova greška danas rijetka, ipak se može pojaviti, a problem rješava kombinacija naredbi find i xargs.

I napomena, bez opcije "-maxdepth 1", find bi našao, a xargs s naredbom rm rekurzivno obrisao sve slike u direktorijima ispod trenutnog. Dakle, pripazite kod uporabe da ne biste obrisali nešto što niste htjeli. Iz tog razloga preporučujemo da rabite "| xargs echo rm" prije izvršavanja prave naredbe. Tako ćete moći vidjeti što će se dogoditi, i na vrijeme reagirati ukoliko rezultat nije ono što želite. Naredbu echo nakon zadovoljavajućeg rezultata jednostavno obrišite.

Još jedan čest slučaj uporabe naredbe xargs uključuje operacije nad datotekama koje imaju razmake ili specijalne karaktere u imenu. Rezultat bez dodatnih opcija neće biti ono što ste očekivali, jer će imena datoteka biti razlomljena na praznim mjestima:

$ touch datoteka.txt
$ touch "datoteka s razmacima u imenu.txt"
$ find *.txt
datoteka.txt
datoteka s razmacima u imenu.txt
$ find *.txt | xargs rm
rm: cannot remove `datoteka': No such file or directory
rm: cannot remove `s': No such file or directory
rm: cannot remove `razmacima': No such file or directory
rm: cannot remove `u': No such file or directory
rm: cannot remove `imenu.txt': No such file or directory
$ ls *.txt
datoteka s razmacima u imenu.txt

Vidimo da je datoteka datoteka.txt uredno obrisana, ali datoteka s razmacima u imenu nije. Da bi to izbjegli, upotrijebite sljedeće opcije:

$ find *.txt -print0 | xargs -0 rm
$ ls *.txt
ls: cannot access *.txt: No such file or directory

Opcije "-print0" i "-0" označavaju da se parametri ne lome na praznim mjestima ("whitespace", što je skupni naziv za space, tab i newline karaktere), nego se nazivi terminiraju karakterom NULL (ASCII kod 0, u programskim jezicima se označava sa "\0").

Opcija "-print0" naredbe find čini upravo to, i umjesto da svoj ispis terminira sa znakom novog retka, terminira ga sa znakom \0, što je upravo ono što xargs očekuje uz opciju "-0".

Povezano s ovim, pretpostavljeno je ponašanje naredbe xargs da argumente ispisuje u jednom retku:

$ cat datoteka.txt | xargs ping -c1
ping -c1 161.53.X.65 161.53.X.66 161.53.X.67 161.53.X.68

Jasno da ovakva naredbena linija ne pomaže puno, pa ćemo upotrijebiti opciju "-n". Ona ograničava ispis argumenata na određeni broj redaka, a mi ćemo upotrijebiti samo jedan redak, jer nam u ovom trenutku tako odgovara:

# cat datoteka.txt | xargs -n1 ping -c1
ping -c1 161.53.X.65
ping -c1 161.53.X.66
ping -c1 161.53.X.67
ping -c1 161.53.X.68

(Kraći i ispravniji zapis je zapravo xargs -n1 ping -c1 < datoteka.txt, rezultat je jednak).

Do sada smo argumente stavljali na kraj naredbenog retka, ali kako ćemo ubaciti argumente ispred nekog drugog argumenta? Tome služi opcija "-I" (koja automatski uključuje i opciju "-n1").

Opciju "-I" ćemo rabiti primjerice kod prebacivanja ili kopiranja svih datoteka u neki direktorij:

$ ls *.txt | xargs -I {} mv {} dir2

Opcija "-I" zapravo samo određuje koji će niz znakova biti "varijabla" gdje će se smještati ime trenutnog argumenta, no uobičajeno je za to rabiti "{}". Dodatno, ukoliko želimo da se na ekran ispisuje što se trenutno izvršava, upotrijebite opciju "-t":

$ cat datoteka.txt | xargs -t -I {} mv {} dir2
mv dat1 dir2
mv dat2 dir2
mv dat3 dir2
mv dat4 dir2

U datoteci datoteka.txt se nalazi popis datoteka koje treba prebaciti, no isto smo mogli postići naredbama ls, find, ili bilo kojim drugim koje generiraju nekakav popis. Na sličan način možete kopirati datoteke ili ih preimenovati.

Xargs se može rabiti i s interaktivnim naredbama. Ukoliko u datoteci popis.txt imate popis datoteka koje treba izmijeniti, omiljeni editor (vim, joe, pico...) možete pokrenuti i ovako:

$ xargs joe < popis.txt

Što se tiče sadržaja datoteka, ni ovdje nema prepreka:

$ find /etc -name \*.conf | xargs grep -i address

Gornjom kombinacijom naredbi pretražili smo cijeli /etc direktorij u potrazi za ključnom riječi "address".

Vjerujemo da smo opisali najzanimljivije načine uporabe naredbe xargs, a za dodatne primjere jednostavno pretražite web.

Kuharice: 
Kategorije: 
Vote: 
5
Vaša ocjena: Nema Average: 5 (1 vote)