Script de shell de Linux para cada archivo en un directorio Tome el nombre del archivo y ejecute un programa

84

Escenario:

Una carpeta en el sistema Linux. Quiero recorrer cada archivo .xls en una carpeta.

Esta carpeta normalmente consta de varias carpetas, varios tipos de archivo (.sh, .pl, .csv, ...).

Todo lo que quiero hacer es recorrer todos los archivos en la raíz y ejecutar un programa solo en archivos .xls.

Editar:

El problema es que el programa que tengo que ejecutar es 'xls2csv' para convertir de formato .xls a .csv. Entonces, para cada archivo .xls, tengo que tomar el nombre del archivo y agregarlo a .csv.

Por ejemplo, tengo un archivo test.xls y los argumentos para xls2csv son: xls2csv test.xls test.csv

¿Tenía sentido?

ThinkCode
fuente

Respuestas:

199

intento:

for f in *.xls ; do xls2csv "$f" "${f%.xls}.csv" ; done
Ignacio Vázquez-Abrams
fuente
¡Simplemente sorprendente! ¡Funciona perfectamente! Muchas gracias!
ThinkCode
6
Esto es exactamente lo que estaba buscando por una razón completamente diferente. Un poco de edición y es perfecto para mi necesidad específica. Gracias = D Y para cualquiera que no tenga claro lo que hace esto: $ {f% .ext} sustituye el nombre del archivo sin la extensión, por lo que en este ejemplo, se representaría como "filename.csv" en lugar de "filename". xls.csv ".
Viernes
Je, busqué en Google "linux foreach txt file" y encontré esto. Esto era exactamente lo que necesitaba, en realidad estaba tratando de usar xls2csv pero pensé que no encontraría ningún resultado buscando eso :)
akiller
1
$ f tendrá un valor de * .xls si * .xls no coincide con ningún archivo. Verifique mi respuesta si eso es un problema.
AndrewBourgeois
O simplemente puede configurar nullglobpara omitir el ciclo.
Ignacio Vazquez-Abrams
15
for i in *.xls ; do 
  [[ -f "$i" ]] || continue
  xls2csv "$i" "${i%.xls}.csv"
done

La primera línea de las doverificaciones si el archivo "coincidente" realmente existe, porque en caso de que nada coincida en su for, dose ejecutará con "* .xls" como $i. Esto podría ser horrible para tu xls2csv.

Andrés Burgués
fuente
13

Mira el comando de búsqueda .

Lo que buscas es algo como

find . -name "*.xls" -type f -exec program 

Publicado

find . -name "*.xls" -type f -exec xls2csv '{}' '{}'.csv;

ejecutará xls2csv file.xls file.xls.csv

Más cerca de lo que quieres.

Tom
fuente
find -maxdepth 1para excluir subcarpetas. Esto también se convierte en test.xlsen test.xls.csvlugar de test.csv. Así que no es exactamente lo que pidió OP, pero bastante cerca.
efímero
El uso {}como una subcadena de un argumento en lugar de un argumento completo es una extensión GNU, no garantizada por la especificación POSIX para find. Como tal, esta respuesta no es necesariamente portátil para plataformas que no son GNU.
Charles Duffy
4
find . -type f -name "*.xls" -printf "xls2csv %p %p.csv\n" | bash

bash 4 (recursivo)

shopt -s globstar
for xls in /path/**/*.xls
do
  xls2csv "$xls" "${xls%.xls}.csv"
done
ghostdog74
fuente
Excelente solucion. He usado esto para permitirme escribir haml / scss y construir en html / css en tiempo de diseño para un proyecto node.js.
Chris Kemp
1
Esto es completamente peligroso si no confía en que sus nombres de archivo no contengan cosas como $(rm -rf /)... o simplemente espacios en blanco.
Charles Duffy