2012-01-06 28 views
7

Voglio rinominare un gruppo di dir da DIR a DIR.OLD. Idealmente vorrei utilizzare il seguente:Alternative a xargs -l

find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print0 | xargs -0 -r -I file mv file file.old 

Ma la macchina che voglio eseguire questo su ha installato BusyBox e le xargs busybox non supporta l'opzione "-I".

Quali sono alcuni metodi alternativi comuni per la raccolta di una matrice di file e quindi l'esecuzione su di essi in uno script di shell?

+2

Qual è il \ "circa? Che direbbe find per elencare i file chiamati esattamente' "* .y" '(le virgolette saranno passate per trovare e mentre * sarà espanso dalla shell, non troverà nulla e passerà comunque), che dubito esistano. –

+0

Tra le varie opzioni di compilazione per busybox ci sono 'CONFIG_FEATURE_FIND_PRINT0',' CONFIG_FEATURE_FIND_EXEC', 'CONFIG_FEATURE_FIND_EXEC_PLUS' - gli approcci funzioneranno o meno a seconda dei dettagli di come * la * copia è stata compilata. –

risposta

9

È possibile utilizzare -exec e {} caratteristiche del comando find quindi non è necessario alcun tubi a tutti:

find -maxdepth 1 -type d -name "*.y" -mtime +`expr 2 \* 365` -exec mv "{}" "{}.old" \; 

Inoltre non è necessario specificare '' percorso: impostazione predefinita per find. E hai utilizzato delle barre aggiuntive in "*.y". Ovviamente se i nomi dei file non contengono realmente citazioni.

A dire il vero va notato che quella versione con ciclo while read è la più veloce proposta qui. Qui ci sono alcune misure di esempio:

$ cat measure 
#!/bin/sh 
case $2 in 
    1) find "$1" -print0 | xargs -0 -I file echo mv file file.old ;; 

    2) find "$1" -exec echo mv '{}' '{}.old' \; ;; 

    3) find "$1" | while read file; do 
     echo mv "$file" "$file.old" 
    done;; 
esac 
$ time ./measure android-ndk-r5c 1 | wc 
    6225 18675 955493 
real 0m6.585s 
user 0m18.933s 
sys  0m4.476s 
$ time ./measure android-ndk-r5c 2 | wc 
    6225 18675 955493 
real 0m6.877s 
user 0m18.517s 
sys  0m4.788s 
$ time ./measure android-ndk-r5c 3 | wc 
    6225 18675 955493 
real 0m0.262s 
user 0m0.088s 
sys  0m0.236s 

Penso che sia perché find e xargs invoca aggiuntive/bin/sh (in realtà exec(3) lo fa) ogni volta per eseguire un comando, mentre la Shell while ciclo non lo fanno.

Upd: Se la versione busybox è stato compilato senza il supporto -exec opzione per il comando find poi il ciclo while o xargs, suggerito nelle altre risposte (one, two), è il tuo modo.

+0

+1: il comando find viene fornito con l'opzione '-exec'. È un po 'più lento di 'xargs' perché esegue il comando per ogni file trovato. Ma, funziona, e non ha problemi _whitespace_ perché la shell non è coinvolta. Se non puoi usare 'xargs' a causa di problemi di spazio bianco, usa' -exec'. I loop sono altrettanto inefficienti del parametro '-exec' dato che vengono eseguiti una volta per ogni file, ma hanno i problemi di spazio bianco che hanno' xargs'. –

+1

'xargs' esegue anche il comando per ogni file in questo caso, quindi' find' non è più lento. –

+0

Hai ragione. Non ho guardato il comando. Normalmente si usano xargs invece di '-exec' perché xargs combina quanti più file possibile sulla riga di comando ed esegue il comando solo poche volte. –

1

Un'alternativa è quella di utilizzare un ciclo:

find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print | while IFS= read file 
do 
    mv "$file" "$file".old 
done 
+1

'read' usa newline come separatore. O avete bisogno di 'read -0' (ma non sono sicuro che sia implementato in busybox) o avete solo bisogno di' -print'. –

+0

concordato. Ho aggiornato la mia risposta. – dogbane

2
  1. utilizzare un ciclo for. Sfortunatamente non penso che busybox comprenda lo read -0, quindi non sarai in grado di gestire correttamente i newline. Se non è necessario, è più facile da solo:

    find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print | while read file; do mv -- "$file" "$file".old; done 
    
  2. Utilizzare un sh -c come il comando. Notare l'uso un po 'strano di $0 per denominare il primo argomento (sarebbe normalmente il nome dello script e va a $0 e mentre si sopprime lo script con -c, l'argomento va ancora a $0) e l'uso di -n 1 per evitare il batching.

    find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print0 | xargs -0 -r -n 1 sh -c 'mv -- "$0" "$0".old' 
    

ModificaOps: ho dimenticato la find -exec di nuovo.

+0

Busybox non capisce nemmeno print0. Ma il tuo ciclo whie funziona –