A volte può succedere di passare una lista troppo lunga a un comando in bash shell. Il problema si verifica spesso con i comandi che operano sui file come ad esempio cp, mv, ls, tar, ecc. E’ possibile ovviare a questo problema sfruttando una combinazione di find e xargs.

Ad esempio:

$ ls *.P05????.*.log
bash: /usr/bin/ls: Arg list too long

oppure:

$ tar cvf archivio_log_05.tar *.P05????.*log
bash: /usr/bin/tar: Arg list too long

Posso sostituirlo così:

$ find . -type f -name '*.P05????.*.log' | xargs -I {} tar -uf /tmp/archivio_log_05.tar {}

oppure per cancellare file molti file (suggerisco di usare prima ls per visualizzarli e poi di passare alla cancellazione vera e propria)

$ find . -type f -name "*.P05????.*.log" | xargs ls -l
$ find . -type f -name "*.P05????.*.log" | xargs rm -f
$ find . -type f -name "*.P05????.*.log" -exec ls -l {} \;
$ find . -type f -name "*.P05????.*.log" -exec rm -f {} \;

Da notare i singoli apici (o doppi apici) nel comando find, infatti se non metto gli apici ottengo ancora l’errore della lista troppo lunga. Inoltre tutto quello che si trova fra apici singoli non viene automaticamente espanso dalla shell bash. Vedi esempio successivo dove la variabile TIPO_FILE viene convertita solo all’interno degli apici doppi, in caso di apici singoli non viene valorizzata.

$ TIPO_FILE=transaction
$ echo $TIPO_FILE
transaction
$ find . -type f -name '$TIPO_FILE*'  | xargs ls -l | wc -l
22717
$ find . -type f -name "$TIPO_FILE*"  | xargs ls -l | wc -l
4074
$ find . -type f -name "*" | xargs ls -l | wc -l
22716

Infine volevo far notare la velocità di esecuzione di xargs rispetto al parametro exec del find

$ time find . -type f -name "*" | xargs ls -l | wc -l
22716

real    0m0.709s
user    0m0.320s
sys     0m0.450s

$ time find . -type f -name "*" -exec ls -l {} \; | wc -l
22716

real    1m54.847s
user    0m32.235s
sys     1m10.525s

E dulcis in fundo aggiungiamo il parametro -P a xargs che indica il numero di processi in parallelo per velocizzare ancora di più il comando.

$ time find . -type f -name "*" | xargs -P4 ls -l | wc -l
22716

real    0m0.456s
user    0m0.360s
sys     0m0.400s

Attenzione a non esagerare con il numero di processi in parallelo perché dopo una certa soglia le prestazioni non migliorano più di tanto, anzi le prestazioni tendono a degradare.

[ad name=”HTML”]

Ulteriori info Using xargs to do parallel procressing, xargs e coreutils-faq.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.