Quando troverà. -exec COMMAND {} + `esegui COMMAND più volte?


9

Se lo faccio

find . -exec echo {} +

stampa tutti i percorsi su una riga, ovvero il comando echoviene eseguito una sola volta.

Ma secondo man find,

-exec command {} +
    ... the number of invocations of the command will 
be much  less  than  the  number  of matched files. ...

Sembra che in alcune circostanze il comando verrà eseguito più volte. Ho ragione? Si prega di esemplificare.

Risposte:


8

POSIX definito find -exec nome_utilità [argomento ...] {} + come:

La fine dell'espressione primaria deve essere punteggiata da un <semicolon> o da un <plus-sign>. Solo un <plus-sign> che segue immediatamente un argomento contenente solo i due caratteri "{}" deve punteggiare la fine dell'espressione primaria. Gli altri usi di <plus-sign> non devono essere considerati speciali. Se l'espressione primaria è punteggiata da un <semicolon>, l'utilità utility_name deve essere invocata una volta per ogni percorso e il primario deve valutare come vero se l'utilità restituisce un valore zero come stato di uscita. Un nome_utilità o un argomento contenente solo i due caratteri "{}" deve essere sostituito dal percorso corrente. Se un nome_utilità o un argomentostringa contiene i due caratteri "{}", ma non solo i due caratteri "{}", è definito dall'implementazione se find sostituisce quei due caratteri o usa la stringa senza modifiche.

Se l'espressione primaria è punteggiata da un <plus-sign>, il primario deve sempre valutare come vero e i nomi dei percorsi per i quali viene valutato il primario devono essere aggregati in set. L'utilità utility_name deve essere invocata una volta per ogni serie di percorsi aggregati. Ogni invocazione deve iniziare dopo l'aggregazione dell'ultimo percorso nel set e deve essere completata prima che l' utilità di ricerca esca e prima che il primo percorso nel set successivo (se presente) sia aggregato per questo primario, ma non è altrimenti specificato se l'invocazione si verifica prima, durante o dopo le valutazioni di altre primarie. Se qualsiasi invocazione restituisce un valore diverso da zero come stato di uscita, la ricerca l'utilità deve restituire uno stato di uscita diverso da zero. Un argomento contenente solo i due caratteri "{}" deve essere sostituito dall'insieme di nomi di percorso aggregati, con ciascun nome di percorso passato come argomento separato all'utilità invocata nello stesso ordine in cui è stato aggregato. Le dimensioni di qualsiasi set di due o più nomi di percorso devono essere limitate in modo tale che l'esecuzione dell'utilità non provochi il superamento del limite {ARG_MAX} del sistema . Se è presente più di un argomento contenente i due caratteri "{}", il comportamento non è specificato.

Quando la lunghezza impostata del nome file trovato supera il sistema ARG_MAX, il comando viene eseguito.

Puoi ARG_MAXusare getconf :

$ getconf ARG_MAX
2097152

Su alcuni sistemi, il valore effettivo di ARG_MAXpuò essere diverso, è possibile fare riferimento qui per maggiori dettagli.


Ho eseguito un esperimento utilizzando find / -exec echo | wce misurando il rapporto tra il conteggio dei caratteri e il conteggio delle righe. Ho scoperto che la lunghezza massima della riga di comando utilizzata findè significativamente inferiore al limite teorico POSIX e molto più vicina alla Size of command buffer we are actually usingriga nell'output da xargs --show-limits. Questo è vero per Linux e può essere vero per l'implementazione di Mac OS find, sebbene xargsnon stampi il valore in Mac OS. Qualche idea sul perché questo accada?
pqnet,

--show-limitsnon è specificato da POSIX, l'implementazione di Mac OS xargsnon lo supporta. find / -exec echo | wcnon funzionerà. Ricorda che ARG_MAXrestituiscono byte. Ed è la lunghezza massima degli argomenti per le exec(3)funzioni.
cuonglm,

So che --show-limitsnon è POSIX, sebbene questa non sia la lunghezza massima dell'argomento utilizzata da find, che utilizza un valore inferiore. Non capisco perché dici che find / -exec echo | wcnon funzionerà: secondo me è un buon modo per avere una stima del valore reale (e da quello che posso vedere, meglio dell'uso getconf ARG_MAX). Inoltre, il mio filesystem è principalmente se non tutto il carattere ASCII, quindi il numero di caratteri è approssimativamente uguale al numero di byte.
pqnet,

@pqnet: usa find / -exec sh -c 'echo $@ | wc -c' _ {} +isntead.
cuonglm,

scusate l'ho scritto male, l'ho effettivamente usatofind / -exec echo {} + | wc -lc
pqnet il

7

Esiste una lunghezza massima dell'elenco di argomenti per un nuovo processo nel sistema POSIX. findsuddividerà l'esecuzione se i percorsi dei file sono più lunghi di questo. Per vedere il limite su Linux, usa xargs --show-limits(non funziona in Mac OS, se qualcuno conosce un'alternativa migliore, commenta qui)

modifica: rubato direttamente dalla risposta di Gnouc, il modo POSIX per ottenere la lunghezza massima dell'elenco di argomenti è getconf ARG_MAX. Tuttavia, ho eseguito un esperimento sul mio computer Mac OS e sembra che findutilizzi poco più della metà di quel numero. Ciò è coerente con il fatto che, sul sistema in cui funziona, xargs --show-limitsci dice che non utilizzerà la lunghezza massima dell'argomento (anche in questo caso utilizzerà circa la metà di quel numero), tuttavia non sono riuscito a trovare una spiegazione per quello.

modifica 2: sembra che l'unico modo affidabile per determinare quanti parametri findsi uniranno per ogni invocazione è sperimentare, ad esempio eseguendo

find / -exec echo {} + | wc -cl

Poiché l'output da findha una riga per ogni echoinvocazione, è possibile contarli usando wc -l. Il numero totale di byte echoed è invece l'output di wc -c. Dividendo l'uno per l'altro si ottiene il numero medio di byte nei parametri per ogni invocazione di comando (anche se un valore leggermente inferiore, a causa dell'arrotondamento, circa la metà della lunghezza media di un percorso nel sistema)


xargsnon utilizza l'intera lunghezza massima dell'argomento perché molti programmi antepongono alcuni argomenti aggiuntivi e quindi passano gli argomenti ad altri programmi. Se xargsriempie gli argomenti al massimo assoluto, tali programmi si rompono, perché non ci sarebbe spazio per quegli argomenti extra.
hvd,

@hvd ha senso. Ma poi, esiste un modo POSIX per sapere quanta parte del buffer viene utilizzata da xargso find?
pqnet,

Puoi eseguirlo con un lungo elenco di argomenti, determinando quanti argomenti sono stati passati nella prima invocazione (qualcosa del genere yes . | xargs | head -n 1 | wc -c) e confrontandolo con l'output di getconf ARG_MAX. Ma, in realtà provandolo sul mio sistema, ottengo una differenza così grande che sembra che ci sia più di ciò di cui sono a conoscenza.
hvd,

quindi si riduce alla sperimentazione ... Aggiornerò la mia risposta
pqnet,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.