Tengo un script que busca todos los archivos en múltiples subcarpetas y archivos para tar. Mi guion es
for FILE in `find . -type f -name '*.*'`
do
if [[ ! -f archive.tar ]]; then
tar -cpf archive.tar $FILE
else
tar -upf archive.tar $FILE
fi
done
El comando find me da el siguiente resultado
find . -type f -iname '*.*'
./F1/F1-2013-03-19 160413.csv
./F1/F1-2013-03-19 164411.csv
./F1-FAILED/F2/F1-2013-03-19 154412.csv
./F1-FAILED/F3/F1-2011-10-02 212910.csv
./F1-ARCHIVE/F1-2012-06-30 004408.csv
./F1-ARCHIVE/F1-2012-05-08 190408.csv
Pero la variable ARCHIVO solo almacena la primera parte de la ruta ./F1/F1-2013-03-19 y luego la siguiente parte 160413.csv .
Traté de usar readcon un bucle while,
while read `find . -type f -iname '*.*'`; do ls $REPLY; done
pero me sale el siguiente error
bash: read: `./F1/F1-2013-03-19': not a valid identifier
¿Alguien puede sugerir una forma alternativa?
Actualizar
Como se sugiere en las respuestas a continuación, actualicé los scripts
#!/bin/bash
INPUT_DIR=/usr/local/F1
cd $INPUT_DIR
for FILE in "$(find . -type f -iname '*.*')"
do
archive=archive.tar
if [ -f $archive ]; then
tar uvf $archive "$FILE"
else
tar -cvf $archive "$FILE"
fi
done
La salida que obtengo es
./test.sh
tar: ./F1/F1-2013-03-19 160413.csv\n./F1/F1-2013-03-19 164411.csv\n./F1/F1-2013-03-19 153413.csv\n./F1/F1-2013-03-19 154412.csv\n./F1/F1-2012-09-10 113409.csv\n./F1/F1-2013-03-19 152411.csv\n./.tar\n./F1-FAILED/F3/F1-2013-03-19 154412.csv\n./F1-FAILED/F3/F1-2013-03-19 170411.csv\n./F1-FAILED/F3/F1-2012-09-10 113409.csv\n./F1-FAILED/F2/F1-2011-10-03 113911.csv\n./F1-FAILED/F2/F1-2011-10-02 165908.csv\n./F1-FAILED/F2/F1-2011-10-02 212910.csv\n./F1-ARCHIVE/F1-2012-06-30 004408.csv\n./F1-ARCHIVE/F1-2011-08-17 133905.csv\n./F1-ARCHIVE/F1-2012-10-21 154410.csv\n./F1-ARCHIVE/F1-2012-05-08 190408.csv: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

IFS=$'\n'antes del bucle `for para que se analice por cada líneaRespuestas:
Usar
forconfindes el enfoque incorrecto aquí, vea por ejemplo este artículo acerca de la lata de gusanos que está abriendo.El enfoque recomendado es usar
find,whileyreadcomo se describe aquí . A continuación se muestra un ejemplo que debería funcionar para usted:De esta manera, delimita los nombres de archivo con caracteres nulos (
\0), esto significa que la variación en el espacio y otros caracteres especiales no causarán problemas.Para actualizar un archivo con los archivos que
findlocaliza, puede pasar su salida directamente atar:Tenga en cuenta que no tiene que diferenciar si el archivo existe o no,
tarlo manejará con sensatez. También tenga en cuenta el uso de-printfaquí para evitar incluir el./bit en el archivo.fuente
./como alquitrán../.tar tar: ./archive.tar: file is the archive; not dumpedif [[ "$FILE" == "./" ]]; thencontinue./bit con-printfver respuesta actualizada. Sin embargo, no debería hacer ninguna diferencia si está incluido o no, ya que solo hace referencia al directorio actual. También incluí unafind/tarcombinación alternativa que es posible que desee utilizar.sortlos resultados antes de repetirlos, necesitaránsort -zel separador nulo.Intenta citar el
forciclo así:Sin comillas, bash no maneja bien los espacios y las nuevas líneas (
\n) ...También intente configurar
fuente
commpara comparar listados de archivos ordenados y los nombres de los archivos tenían espacios en ellos, a pesar de las variables de cita no funcionaba. Luego vi cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html y la solución de configurar $ IFS con IFS = $ (echo -en "\ n \ b") funcionó para mí.Esto funciona y es más simple:
Gracias a Rupa ( https://github.com/rupa/z ) por esta respuesta.
fuente
Además de las citas adecuadas, puede indicar
findque use un separador NULL, y luego leer y procesar los resultados en unwhilebucleEsto debería manejar cualquier nombre de archivo que sea compatible con POSIX - ver
man findfuente
fuente
Hice algo como esto para encontrar archivos que pueden contener espacios.
Trabajado como un encanto :)
fuente
La mayoría de las respuestas aquí se rompen si hay un carácter de nueva línea en el nombre del archivo. Utilizo la fiesta más de 15 años, pero solo interactiva.
En Python puede usarnos os.walk (): http://docs.python.org/2/library/os.html#os.walk
Y el módulo tarfile: http://docs.python.org/2/library/tarfile.html#tar-examples
fuente
Creo que es mejor que
finduses la opción 's -exec.A continuación, Buscar ejecuta el comando mediante una llamada al sistema, de modo que se conservan los espacios y las nuevas líneas (en lugar de una tubería, lo que requeriría el uso de caracteres especiales). Tenga en cuenta que "tar -c" funciona si el archivo ya existe o no, y que (al menos con bash) ni {} ni + necesitan ser citados.
fuente
Como sugirió minerz029, debe citar la expansión del
findcomando. También necesita citar todas las sustituciones de$FILEen su ciclo.Tenga en cuenta que la
$()sintaxis debe preferirse al uso de backticks; mira esta pregunta de U&L . También eliminé la[[palabra clave y la reemplacé por el[comando porque es POSIX.fuente
[[y[, parece que[[es más nuevo y admite más funciones, como globing y regex. sin embargo,[[solo está enbashsh[[apoyo global. De acuerdo con la wiki de Greg , no se producen burbujas en el interior[[.[ "ab" == a? ] && echo "true"entonces[[ "ab" == a? ]] && echo "true"a*significa "seguido de cualquier número de caracteres" en lugar de "todos los archivos cuyos nombres comienzanay tienen cualquier número de caracteres después". Trate[ ab = a* ] && echo truevs[[ ab == a* ]] && echo true.[[todavía hace expresiones regulares mientras[que no. Debe haberse confundido