Newsgroup: it.comp.os.linux.iniziare
Titolo: |xargs eseguito almeno una volta

Salve.
Ho uno script che lancia un comando che manda il suo output in pasto a
un altro comando con xargs.
esempio
ls|xargs rm
questo cancella tutti i file della directory (equivale a rm *, ma
prendiamolo solo come esempio)
il problema è che se ls non da nessun output (directory vuota), il
comando rm viene eseguito comunque e chiaramente mi va in errore
perchè non ha parametri
supponiamo ora che il comando sia alquanto distruttivo...
il seguente è un esempio da perfetti masochisti (o idioti... scegliete
voi), ma rende il fatto che non uno non si sarebbe aspettato l'errore:
# pwd
/
#
# find /x -ls
196609    4 drwxr-xr-x   2 root     root         4096 Sep 22 13:15 /x
196610    0 -rw-r--r--   1 root     root            0 Sep 22 13:15 /x/
pippo
196611    4 drwxr-xr-x   2 root     root         4096 Sep 22 13:21 /x/
y
#
voglia di eliminare tutte le sottodirectory (e solo quelle) di /x...
# find /x/* -type d
/x/y
# find /x/* -type d|xargs rm -rf
#
vi garantisco che funziona..
se per caso lo rilancio ora, che non ci sono sottodirectory:
# find /x/* -type d
#
uno si aspetterebbe che
# find /x/* -type d|xargs rm -rf
semplicemente non facesse nulla
potete provarlo, ma prima fatevi un backup dell'intero sistema :-)
infatti
# find /x/* -type d|xargs ls
bin  boot  dev  etc  home ...
ls è stato lanciato comunque, anche se l'input dava 0 righe (non una
riga vuota, ma zero righe), e senza parametri, il che implica che darà
un output.
morale.
nessuno (si spera) farà una cosa di cui sopra o simile, ma il sistema
viene usato anche per altri scopi.
Esempio di un comando usato per creare un pacchetto:
find . | xargs file | grep "current ar archive" | cut -f 1 -d : |
xargs strip -g 2> /dev/null
se lo script non trova nessuna libreria questo va avanti, ma se
appresso ci metto un echo $? mi restituisce 123, errore che io potrei
evitare di trappare, ma il "set -e" che ci ho messo non lo ignora
conosco la gestione delle pipe e so che
ls|cat esegue il comando cat anche se ls non tira fuori output, e di
conseguenza anche xargs sopra viene eseguito,
ma mi sarei aspettato che xargs fosse sufficientemente intelligente da
non avviare il suo comando se in input non trova nulla.
Matteo

 perchè non ha parametri
man xargs
-r

 -r
Strano, il man l'avevo visto, ma questa mi deve essere sfuggita..
grazie.
Matteo

 non avviare il suo comando se in input non trova nulla.
grazie per il post... non ci avevo mai pensato...
comunque non mi pare faccenda di xargs valutare la presenza o meno di 
output da passare al comando... secondo me cosi' come si comporta va 
benissimo
ad ogni modo io risolverei cosi'...
find /x/* -type d | while read a; do rm -fr $a; done

 
ti dico un'altra cosa che ti puo' interessare
quando fai una pipe, all'uscita puoi guardare la tabella PIPESTATUS, e 
vedere i vari codice d'uscita dei comandi
nel tuo caso, ammesso che non ci siano file
$ find . | xargs file | grep "current ar archive" | cut -f 1 -d : |
xargs strip -g 2> /dev/null
$ echo ${PIPESTATUS[@]}
0 0 1 0 123
il $? ti da solo l'ultimo...
ciao


già, infatti il set -e esce sull'ultimo errore non gestito (dovrebbe
essere scritto nel man di bash, mi sembra), in questo caso xargs, per
la precisione
       123 if any invocation of the command exited with status 1-125
il problema si risolve comunque con un xargs -r oppure con
( find . | xargs file | grep "current ar archive" | cut -f 1 -d : |
xargs strip -g 2> /dev/null )
così l'errore non viene intercettato da set -e
Ciao,
Matteo

 cosě l'errore non viene intercettato da set -e
si puo' anche fare in modo piu' 'snello'...
find . | xargs file | grep "current ar archive" | cut -f 1 -d : |
 > xargs strip -g 2> /dev/null || :

  > xargs strip -g 2> /dev/null || :
veramente la primissima soluzione è stata:
find . | xargs file | grep "current ar archive" | cut -f 1 -d : |
xargs strip -g |true 2> /dev/null
Matteo

 xargs strip -g |true 2> /dev/null
'true' non ha nessun tipo di output... non serve redirigere il suo stderr
rimane comunque, credo, piu' snello l'altro modo...
facendo '| true' aggiungi comunque una pipe alla catena...
con '|| true' invece non aggiungi nessuna pipe, e se non esce con 
errore, 'true' neanche lo esegui...


dico che il |true è quello che avevo usato, non la soluzione migliore.
la redirezione era per xargs, quindi sarebbe stato più corretto
..|xargs strip -g 2>/dev/null |true
true non ha nessun tipo di output, ma l'ho usato per garantirmi che
l'error code fosse zero.
che poi ||: sia migliore non lo metto in dubbio (anche se non so cosa
facciano i : da soli, effettivamente)
comunque la meno invasiva (alias non modificare troppo il codice), è
stata quella di mettere
(
find....
)
perchè alcuni script l'avevano ed altri no. quindi ho unificato.
inoltre le probabili find con errore sono >=1 <=3 a seconda dello
script
(
find..
find..
find..
)
Matteo
P.S: jas sono sempre io, sbagliando account.

 facciano i : da soli, effettivamente)
e' il NOP di bash
non fanno niente!