2012-05-09 22 views
163

Podría alguien proporcionar el código para hacer lo siguiente: Suponga que hay un directorio de archivos, que deben ejecutarse a través de un programa. El programa envía los resultados a la salida estándar. Necesito un script que vaya a un directorio, ejecute el comando en cada archivo y concatene la salida en un archivo de salida grande.Script Bash para ejecutar el comando en todos los archivos en un directorio

Por ejemplo, para ejecutar el comando en el archivo 1:

$ cmd [option] [filename] > results.out 
+3

me gustaría agregar a la pregunta. ¿Se puede hacer usando xargs? por ejemplo, 'ls | xargs cmd [opciones] {nombres de archivos puestos aquí automáticamente por xargs} [más argumentos]> results.out' –

+0

Puede, pero es probable que [no desee usar 'ls'] (http: //mywiki.wooledge. org/ParsingLs) para conducir 'xargs'. Si 'cmd' está redactado competentemente, quizás simplemente haga' cmd '. – tripleee

Respuesta

244

El siguiente código de fiesta pasará $ archivo para comandar donde archivo $ representará a todos los archivos en/dir

for file in /dir/* 
do 
    cmd [option] "$file" >> results.out 
done 

Ejemplo

[email protected] ~/foo $ touch foo.txt bar.txt baz.txt 
[email protected] ~/foo $ for i in *.txt; do echo "hello $i"; done 
hello bar.txt 
hello baz.txt 
hello foo.txt 
+13

Si no existen archivos en'/dir/', entonces el ciclo todavía se ejecuta una vez con un valor de '*' para' $ file', lo que puede ser indeseable. Para evitar esto, habilite nullglob durante la duración del ciclo. Agregue esta línea antes del bucle 'shopt -s nullglob' y esta línea después del bucle' shopt -u nullglob #revert nullglob vuelva a su estado predeterminado normal'. –

+29

+1, y me acaba de costar toda mi colección de papeles pintados. todos después de mí, usa las dobles comillas. "$ file" – Behrooz

+0

Si el archivo de salida es el mismo dentro del bucle, es mucho más eficiente redirigir fuera del bucle 'done> results.out' (y probablemente entonces puede sobrescribir en lugar de agregar, como he supuesto aquí). – tripleee

112

¿Qué tal esto:

find /some/directory -maxdepth 1 -type f -exec cmd option {} \; > results.out 
  • -maxdepth 1 argumento impide que se encuentran de forma recursiva descendente en cualquier subdirectorio. (Si desea que dichos directorios anidados se procesen, puede omitir esto.)
  • -type -f especifica que solo se procesarán los archivos sin formato.
  • -exec cmd option {} dice que se ejecute cmd con el option especificado para cada archivo encontrado, con el nombre sustituido por {}
  • \; denota el final del comando.
  • Por último, la salida de todos los cmd ejecuciones individuales se redirige a results.out

Sin embargo, si usted se preocupa por el orden en que se procesan los archivos, puede ser mejor escribir un bucle. Creo que find procesa los archivos en orden de inodo (aunque podría estar equivocado al respecto), que puede no ser lo que desea.

+1

Esta es la forma correcta de procesar archivos. Usar un bucle for es propenso a errores debido a muchas razones. También se puede ordenar usando otros comandos como 'stat' y' sort', que por supuesto depende de los criterios de clasificación. – tuxdna

+0

si quisiera ejecutar dos comandos, ¿cómo los vincularía después de la opción '-exec'? ¿Tengo que envolverlos en comillas simples o algo así? – frei

+0

'encontrar' siempre es la mejor opción, ya que puede filtrar por patrón de nombre de archivo con la opción' -name' y puede hacerlo en un solo comando. –

22

que esté haciendo esto en mi Raspberry Pi desde la línea de comandos ejecutando:

for i in *;do omxplayer "$i";done 
1

que necesitaba para copiar todos los archivos .MD de un directorio a otro, así que aquí está lo que hice.

for i in **/*.md;do mkdir -p ../docs/"$i" && rm -r ../docs/"$i" && cp "$i" "../docs/$i" && echo "$i -> ../docs/$i"; done

que es bastante difícil de leer, por lo que permite descomponerlo.

primer cd en el directorio con los archivos,

for i in **/*.md; para cada archivo en su patrón de

mkdir -p ../docs/"$i" hacer ese directorio en una carpeta de documentos fuera de la carpeta que contiene sus archivos. Lo cual crea una carpeta adicional con el mismo nombre que ese archivo.

rm -r ../docs/"$i" eliminar la carpeta adicional que se crea como resultado de mkdir -p

cp "$i" "../docs/$i" Copia el archivo real

echo "$i -> ../docs/$i" Echo lo que hizo

; done vivir felices para siempre

1

Una rápida y la manera sucia que hace el trabajo a veces es:

Por ejemplo, para encontrar el número de líneas en todos los archivos en el directorio actual, que puede hacer:

find . | xargs wc -l 
Cuestiones relacionadas