linux - vendita - sdr usb receiver




trovare-exec una funzione di shell in Linux? (8)

I risultati di elaborazione alla rinfusa

Per aumentare l'efficienza, molte persone usano xargs per elaborare i risultati alla rinfusa, ma è molto pericoloso. Per questo motivo è stato introdotto un metodo alternativo in find che esegue risultati in massa.

Si noti tuttavia che questo metodo potrebbe presentare alcuni avvertimenti come ad esempio un requisito in POSIX: find {} alla fine del comando.

export -f dosomething
find . -exec bash -c 'for f; do dosomething "$f"; done' _ {} +

find passerà molti risultati come argomenti ad una singola chiamata di bash e il for -loop itererà attraverso quegli argomenti, eseguendo la funzione dosomething su ognuno di questi.

La soluzione precedente avvia gli argomenti a $1 , motivo per cui esiste un _ (che rappresenta $0 ).

Elaborazione dei risultati uno per uno

Allo stesso modo, penso che la risposta accettata dovrebbe essere corretta

export -f dosomething
find . -exec bash -c 'dosomething "$1"' _ {} \;

Questo non è solo più sano di mente, perché gli argomenti dovrebbero sempre iniziare da $1 , ma anche usando $0 potrebbe portare a comportamenti imprevisti se il nome del file restituito da find ha un significato speciale per la shell.

C'è un modo per trovare find l'esecuzione di una funzione che definisco nella shell? Per esempio:

dosomething () {
  echo "doing something with $1"
}
find . -exec dosomething {} \;

Il risultato è:

find: dosomething: No such file or directory

C'è un modo per find es- -exec vedere il dosomething ?


Aggiungi le citazioni in {} come mostrato di seguito:

export -f dosomething
find . -exec bash -c 'dosomething "{}"' \;

Corregge qualsiasi errore dovuto ai caratteri speciali restituiti da find , ad esempio i file con parentesi nel loro nome.


La risposta di Jak sopra è grande ma ha un paio di insidie ​​che sono facilmente superabili:

find . -print0 | while IFS= read -r -d '' file; do dosomething "$file"; done

Questo utilizza null come delimitatore invece di un avanzamento riga, quindi i nomi dei file con i linefeed funzioneranno. Usa anche il flag -r che disabilita l'escape del backslash, senza che i backslash nei nomi dei file non funzionino. Elimina inoltre IFS modo che i potenziali spazi bianchi finali nei nomi non vengano scartati.


Metti la funzione in un file separato e find di eseguirla.

Le funzioni della shell sono interne alla shell in cui sono definite; find non sarà mai in grado di vederli.


Non direttamente, no. Trova è in esecuzione in un processo separato, non nella shell.

Crea uno script di shell che fa lo stesso lavoro della tua funzione e trova può -exec quello.


Per quelli di voi che cercano una funzione bash che eseguirà un determinato comando su tutti i file nella directory corrente, ne ho compilato uno dalle risposte precedenti:

toall(){
    find . -type f | while read file; do "$1" "$file"; done
}

Si noti che si rompe con i nomi dei file contenenti spazi (vedi sotto).

Ad esempio, prendi questa funzione:

world(){
    sed -i 's_hello_world_g' "$1"
}

Dire che volevo cambiare tutte le istanze di ciao al mondo in tutti i file nella directory corrente. Farei:

toall world

Per sicurezza con qualsiasi simbolo nei nomi dei file, usare:

toall(){
    find . -type f -print0 | while IFS= read -r -d '' file; do "$1" "$file"; done
}

(ma hai bisogno di un find che gestisca -print0 ad esempio, GNU find ).


Trovo il modo più semplice come seguire, ripetendo due comandi in singola do

func_one () {
  echo "first thing with $1"
}

func_two () {
  echo "second thing with $1"
}

find . -type f | while read file; do func_one $file; func_two $file; done

-exec usare -exec tutto. Perché non usare xargs ?

find . -name <script/command you're searching for> | xargs bash -c




bsd