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 read
con 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
for
confind
es 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
,while
yread
como 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
find
localiza, puede pasar su salida directamente atar
:Tenga en cuenta que no tiene que diferenciar si el archivo existe o no,
tar
lo manejará con sensatez. También tenga en cuenta el uso de-printf
aquí para evitar incluir el./
bit en el archivo.fuente
./
como alquitrán../.tar tar: ./archive.tar: file is the archive; not dumped
if [[ "$FILE" == "./" ]]; then
continue
./
bit con-printf
ver 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/tar
combinación alternativa que es posible que desee utilizar.sort
los resultados antes de repetirlos, necesitaránsort -z
el separador nulo.Intenta citar el
for
ciclo así:Sin comillas, bash no maneja bien los espacios y las nuevas líneas (
\n
) ...También intente configurar
fuente
comm
para 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
find
que use un separador NULL, y luego leer y procesar los resultados en unwhile
bucleEsto debería manejar cualquier nombre de archivo que sea compatible con POSIX - ver
man find
fuente
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
find
uses 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
find
comando. También necesita citar todas las sustituciones de$FILE
en 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á enbash
sh
[[
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 comienzana
y tienen cualquier número de caracteres después". Trate[ ab = a* ] && echo true
vs[[ ab == a* ]] && echo true
.[[
todavía hace expresiones regulares mientras[
que no. Debe haberse confundido