20 Temmuz 2020 Pazartesi

xargs komutu

Giriş
xargs pipe ile verilen çıktıyı her satır için çalıştırır. xargs ile komutlar paralelleştirme imkanı vardır.

Exist Status
Açıklaması şöyle
0 if it succeeds
123 if any invocation of the command exited with status 1-125
124 if the command exited with status 255
125 if the command is killed by a signal
126 if the command cannot be run
127 if the command is not found
1 if some other error occurred.
Örnek
Elimizde şöyle bir komut olsun. history bir built-in komut olduğu için xargs bu komutu bulamaz ve 127 döner.
echo 1 | xargs history -d; echo $?
argument list too long
argument list too long hatası alıyorsak xargs ile durumu düzeltebiliriz. 

Örnek
Mesela her .gz dosyasını gunzip ile açmak istiyoruz ancak çok fazla dosya varsa, shell bize bu komut için hata veriyorsa
find /my/dir -name "*.pdb.gz" -execdir gunzip "{}" \;
Şöyle düzeltebiliriz. Burada gunzip komutu arka arkaya bir sürü dosya ismi alabildiği için sorun çıkmıyor.
find . -type f -a -name \*.pdb.gz -print0 | xargs -0 gunzip
Örnek
Şöyle yaparız. find komutu -print0 ile kullanılıyor. Her dosya ismi 0 karakteri ile biter. xargs ta -0 ile kullanıyor. Dosya isimleri arasında 0 karakteri olduğunu belirtiriz. Burada doit scripti  arka arkaya bir sürü dosya ismi ile çağrılır
find /path/to/files -type f -print0 | \
    xargs -0 -r $HOME/bin/doit
Script'in şöyle olması gerekir.
#!/bin/bash
while [[ $# -ne 0 ]] ; do
    thisfile="$1"
    shift
    dos2unix -k -n "$thisfile" tmp_file
    mv tmp_file "$thisfile"
done
Dosya isminin Konumu - {} karakterleri
Konum tanımlamazsak satırı komutun sonuna ekler.

find . -name *.cpp | xargs rm -rf

Konum tanımlamak için {} kullanılır. Örnek:
ls -tr | tail -n 3 | xargs -I{} mv {} /home/user/Desktop
-d seçeneği - delimeter
Input delimeter'ın ne olacağını belirtir.
Örnek
Açıklaması şöyle.
-d'\n' tells xargs to treat each line of input as a separate file name.
Her satıra karşılık gelen dosya açmak için şöyle yaparız
xargs -d '\n' touch -- < path/to/ls.txt
Örnek
İlk 4 satırı tek satır haline getirmek için şöyle yaparız.
xargs -d '\n' -n4 < inputfile.txt
-i[replace-str], --replace[=replace-str] seçeneği
Açıklaması şöyle.
This option is a synonym for -I replace-str if replace-str is specified. If the replace-str argument is missing, the effect is the same as -I{}. This option is deprecated; use -I instead.
-I seçeneği - replace str
Açıklaması şöyle.
Replace occurrences of replace-str in the initial-arguments with names read from standard input. Also, unquoted blanks do not terminate input items; instead the separator is the newline character. Implies -x and -L 1.
Pipe ile verilen çıktıyı satırlara böler. tail gibi programlar satırları kendileri bölmediği için gerekebilir.

-I {} seçeneği
Açıkaması şöyle.
"with names read from standard input" means that xargs takes the data coming in on its standard input, splits it up, and uses it to run the command given in its arguments. By default, it splits on blanks or newlines, and runs echo with as many arguments at a time as possible.
...
The -I option changes the way the new command lines are built. Instead of adding as many arguments as possible at a time, xargs will take one name at a time from its input, look for the given token ({} here) and replace that with the name.
Örnek
Şöyle yaparız.
cat foo | xargs -I{} echo {}
-L seçeneği - max lines
Belirtilen satır sayısı sayı kadar satırı işler.
Örnek
Şöyle yaparız. myfile dosyasında her satırı okur ve myScript'e geçer.
xargs -l1 <myFile myScript
Açıklaması şöyle.
-l1 tells xargs to run myScript once for each 1 line of input, with the words on that 1 line passed as separate arguments.
Örnek
Şöyle yaparız. Her bir dosya için chmod +x komutu çalıştırılıyor.
find . -maxdepth 1 -type f -print0 | xargs -L1 -p0 chmod +x
-n seçeneği - max arguments
Örnek
Şöyle yaparız.
$ while date +%H:%S; do sleep 1; done | xargs -n2 echo
16:51 16:52
16:53 16:54
16:55 16:56
16:57 16:58
^C
-o seçeneği - tty kullanabilmeyi sağlar
Açıklaması şöyle. Normalde xargs interactive değildir dolayısıyla tty açmaz.
  -o, --open-tty
          Reopen stdin as /dev/tty in the child process before
          executing the command.  This is useful if you want xargs
          to run an interactive application.
xargs tty açmadığı için şu komut hata verir
$ pgrep gvfs | paste -s -d ',' | xargs -t top -p
top -p 1598,1605,1623,1629,1635,1639,1645,1932,2744
top: failed tty get
Düzeltmek için şöyle yaparız
pgrep gvfs | paste -s -d ',' | xargs --open-tty top -p
-P seçeneği - max processes
Komutları paralel hale getirmek için -n 1 ile komuta tek bir parametre verilmesi sağlarnı

Örnek - Palelleştirme
En fazla 100 process başlatmak için şöyle yaparız
printf '%s\n' file*.txt | xargs -n 1 -P 100 perl dataProcessing.pl
Örnek - Palelleştirme
İşlemci sayısı kadar gzip'i paralel başlatmak için şöyle yaparız.
 -t çalıştırılan komutu konsola yazar. 
-r girdi string boşsa komutu çalıştırmaz.
-0 ile girdiler arasında NULL byte delimiter kullanılır. 
-n ile her komuta en fazla 1 parametre verilir.
-P ile işlemci sayısı kadar komutu başlatılır.
find -type f -not -name '*.gz' -print0 | xargs -tr0n 1 -P$(nproc) gzip
-p prompt seçeneği
Interactive anlamına gelir. Kullanıcıdan y veya Y gelirse komutu çalıştırır.
Örnek
Şöyle yaparız. Sadece y ile cevap verilen dosyalar için chmod komutu çalıştırılır.
find . -maxdepth 1 -type f -print0 | xargs -L1 -p0 chmod +x
-t seçeneği
Çalıştırılan komutu konsola yazar

-0 seçeneği - Ayraç olarak null kullanır
xargs normalde dosya isminde ayraç olarak whitespace kullanır. Ancak bazı dosya isimlerinin içinde boşluk olabiliyor. Bu gibi durumlarda Windows'ta dosya ismi tırnak içine alınır. Ancak bir çok program dosya ismini tırnak ile üretemez. Bu durumda xargs'a dosya isimleri için ayraç farklı bir şey kullanmasını söylemek gerekir. Ayraç olarak genellikle null karakteri kullanılır.

Örnek
Şöyle yaparız. find -print0 ile dosya isimleri arasına null koyar. xargs ise ayraç olarak null kullanır. ve 1 MB'den büyük dosyalar silinir.
find . -size +1M -print0 | xargs -r0 rm --
Örnek
Şöyle yaparız. Burada print sonucunda içinde boşluk olan bir çıktı üretiliyor. Bunu ssh komutuna geçiyoruz. ssh ta karşı makinede çalışacak xargs komutuna geçiyor
printf '%s\0' "$DEST_PATH/subdir1" "$DEST_PATH/subdir2" |
  ssh -i key 10.10.10.10 'xargs -0 mkdir -p --'
-r seçeneği
Açıklaması şöyle.
-r tells xargs not to run the command if the input file is empty.
Örnek
Şöyle yaparız. Dosyadaki her satır için gzip -d komutunu çalıştırır.
xargs -rd'\n' gzip -d <large_file_list
-s seçeneği - max characters
Okunacak karakter sayısın belirtir. Şöyle yaparız.
printf '%s ' {1..1024} | strace -e read xargs -s 2048 -x
--showlimists seçeneği
Örnek
Şöyle yaparız. Burada Size of command buffer we are actually using satırı önemli. xargs 128 KiB civarnda bir girdi alabiliyor.
$ xargs --show-limits < /dev/null
Your environment variables take up 3456 bytes
POSIX upper limit on argument length (this system): 2091648
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2088192
Size of command buffer we are actually using: 131072
Maximum parallelism (--max-procs must be no greater): 2147483647



Hiç yorum yok:

Yorum Gönder