2012-01-06 16 views
7

Quiero cambiar el nombre de un grupo de directorios de DIR a DIR.OLD. Lo ideal sería utilizar lo siguiente:Alternativas a xargs -l

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

Pero la máquina que quiero para ejecutar esto en cuenta BusyBox instalado y los xargs BusyBox no soporta la opción "-i".

¿Cuáles son algunos métodos alternativos comunes para recopilar una matriz de archivos y luego ejecutarlos en un script de shell?

+2

¿Cuál es el \ "sobre? Eso le diría a find para listar los archivos llamados exactamente' "* .y" '(las comillas se pasarán para encontrar y mientras que * se expandirá por shell, no encontrará nada y pasó a través de todos modos), que sin duda existe. –

+0

Entre las diversas opciones de tiempo de compilación para busybox están 'CONFIG_FEATURE_FIND_PRINT0',' CONFIG_FEATURE_FIND_EXEC', 'CONFIG_FEATURE_FIND_EXEC_PLUS' - los enfoques funcionarán o no, dependiendo de los detalles de cómo se compiló * su * copia. –

Respuesta

9

Puede utilizar -exec y {} características de la orden find por lo que no necesita ningún tubo en todo: ''

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

también que no es necesario especificar ruta: esta es la predeterminada para find. Y usaste barras adicionales en "*.y". Por supuesto, si sus nombres de archivo realmente no contienen comillas.

Para ser justos, debe tenerse en cuenta que la versión con while read es la más rápida propuesta aquí. Aquí están algunas mediciones ejemplo:

$ 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 

Creo que es porque find y xargs invoca/bin/sh adicional (en realidad exec(3) lo hace) cada vez para ejecutar un comando, mientras que la cáscara while bucle no lo hacen.

UPD: Si su versión de busybox fue compilado sin soporte -exec opción para el comando find entonces el bucle while o xargs, sugirió en las otras respuestas (one, two), es su camino.

+0

+1: el comando find viene con la opción '-exec'. Es un poco más lento que 'xargs' porque ejecuta el comando para cada archivo encontrado. Pero funciona, y no tiene problemas con _whitespace_ porque el shell no está involucrado. Si no puede usar 'xargs' debido a problemas con el espacio en blanco, use' -exec'. Los bucles son tan ineficientes como el parámetro '-exec' ya que se ejecutan una vez para cada archivo, pero tienen los problemas de espacio en blanco que' xargs' tiene. –

+1

'xargs' también ejecuta el comando para cada archivo en este caso para que' find' no sea más lento. –

+0

Tienes razón. No miré el comando. Normalmente usas xargs en lugar de '-exec' porque xargs combina tantos archivos como puede en la línea de comandos y ejecuta el comando solo unas pocas veces. –

1

Una alternativa es utilizar un bucle:

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

'leer' utiliza nueva línea como separador. O necesita 'leer -0' (pero no estoy seguro de que esté implementado en busybox) o simplemente necesita' -print'. –

+0

de acuerdo. He actualizado mi respuesta. – dogbane

2
  1. utilizar un bucle for. Lamentablemente, no creo que busybox entienda read -0 tampoco, por lo que no podrá manejar correctamente las nuevas líneas. Si no es necesario, lo más fácil es simplemente:

    find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print | while read file; do mv -- "$file" "$file".old; done 
    
  2. Utilice un sh -c que el comando. Tenga en cuenta el uso un poco extraño de $0 para nombrar el primer argumento (normalmente sería el nombre del script y va a $0 y mientras suprime el script con -c, el argumento sigue en $0) y el uso de -n 1 para evitar el procesamiento por lotes.

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

EditarVaya: Me olvidé de la find -exec nuevo.

+0

Busybox ni siquiera entiende print0. Pero tu whie loop funciona –