El comando find da esta salida:
[root @ localhost /] # find var / log / -iname anaconda. * var / log / anaconda.log var / log / anaconda.xlog var / log / anaconda.yum.log var / log / anaconda.syslog var / log / anaconda.program.log var / log / anaconda.storage.log
Después de combinar con tar, muestra esta salida:
[root @ localhost /] # find var / log / -iname anaconda. * -exec tar -cvf file.tar {} \; var / log / anaconda.log var / log / anaconda.xlog var / log / anaconda.yum.log var / log / anaconda.syslog var / log / anaconda.program.log var / log / anaconda.storage.log
Pero al enumerar el archivo tar, solo muestra un único archivo
[root @ localhost /] # tar -tvf file.tar -rw ------- root / root 208454 2012-02-27 12:01 var / log / anaconda.storage.log
¿Qué estoy haciendo mal aquí?
Con xargs obtengo esta salida:
[root @ localhost /] # find var / log / -iname anaconda. * | xargs tar -cvf file1.tar
Segunda pregunta
Mientras escribe / delante de var, significa find /var/log
por qué le está dando este tar de mesaage : eliminando los principales '/' de los nombres de miembros
[root @ localhost /] # find / var / log / -iname anaconda. * -exec tar -cvf file.tar {} \; tar: eliminando los principales '/' de los nombres de miembros /var/log/anaconda.log tar: eliminando los principales '/' de los nombres de miembros /var/log/anaconda.xlog tar: eliminando los principales '/' de los nombres de miembros /var/log/anaconda.yum.log tar: eliminando los principales '/' de los nombres de miembros /var/log/anaconda.syslog tar: eliminando los principales '/' de los nombres de miembros /var/log/anaconda.program.log tar: eliminando los principales '/' de los nombres de miembros /var/log/anaconda.storage.log
En una forma simple, ¿cuál es la diferencia entre los dos siguientes?
find var/log
y find /var/log
find
comando, debe citar el término de búsqueda. Funciona sin a veces pero no siempre.{} +
lugar de{} \;
eso, agrupará los resultados de find en un argumentoRespuestas:
Nota: Vea la respuesta de @ Iain para una solución algo más eficiente.
Tenga en cuenta que
find
llamará a la-exec
acción para cada archivo que encuentre.Si ejecuta
tar -cvf file.tar {}
para cadafind
salida de archivo individual , esto significa que sobrescribiráfile.tar
cada vez, lo que explica por qué termina con un archivo restante que solo contieneanaconda.storage.log
: son las últimasfind
salidas de archivo .Ahora, realmente desea agregar los archivos al archivo en lugar de crearlo cada vez (esto es lo que hace la
-c
opción). Entonces, use lo siguiente:La
-r
opción se agrega al archivo en lugar de recrearlo cada vez.Nota: Reemplace
-iname anaconda.*
con-iname "anaconda.*"
. El asterisco es un comodín y su caparazón puede expandirlofind
incluso antes de verlo. Para evitar esta expansión, envuelva el argumento entre comillas dobles.En cuanto a
tar
eliminar el encabezado/
: el archivo solo debe contener nombres de archivo relativos . Si agrega archivos con un encabezado/
, se almacenarán como nombres de archivo absolutos , es decir, literalmente/var/…
en su computadora, por ejemplo.IIRC esto es simplemente una precaución para
tar
implementaciones que no sean GNU, y es más seguro de esta manera porque no sobrescribirá sus datos reales/var/…
cuando extraiga el archivo si contiene nombres de archivo relativos.fuente
tar
hacer un archivo de cinta real de esta manera, agregando un archivo a la vez, rebobinando la cinta y volviendo a leer todo cada vez para llegar al final, todo sería ridículamente lento. Su solución solo es adecuada si está escribiendo el archivo tar en el disco.find /var/log/ -iname anaconda*
dando nada yfind /var/log/ -iname anaconda.*
dando la salida, ¿por qué?find
más. Entonces, si tieneanaconda*
, y en su carpeta actual hay algo llamado, por ejemplo,anaconda5
(que coincide con este comodín), el comodín se expandirá yfind
verá en-iname anaconda5
lugar de-iname anaconda*
. El motivo por el cual el primero no funciona y el segundo sí depende de qué archivos estén en su directorio actual. @max{} +
lugar de{} \;
para agrupar los resultados de encontrar en un argumentoPuedes usar algo como:
El
-print0
y-T
trabajar juntos para permitir nombres de archivo con espacios de nueva línea, etc. El final-
le dice a tar que lea los nombres de archivo de entrada desde stdin.Tenga en cuenta que
-print0
debe aparecer al final de su declaración, según esta respuesta . De lo contrario, probablemente obtendrá más archivos de los que esperaba.fuente
-name
opción, causando su solución atar
todo el directorio. Si eso es lo que quieres, puedes hacerlo más fácilmentetar -cvf file.tar var/log
sin usarlofind
.tar
es una buena idea. Definitivamente es la mejor solución si espera que los nombres de las rutas puedan tener espacios. Incluso lo describiría como el mejor técnicamente, ya que es confiable y eficiente. Pero requiere un conocimiento especial adicional de ambosfind
ytar
. Prefiero la sustitución de comandos prácticamente solo porque es una herramienta más general: aprenda a usarla una vez, luego úsela en todas partes. (Pero lo reconozco, estoy en Windows con un shell donde siempre funciona). Disculpas si parecía grosero.xargs
.-print0
opción find , también necesita la--null
opción tar .--no-unquote
resulta que también es necesario: los nombres de archivo que contengan barras invertidas se manejarían de forma incorrecta. (No, esto no es hipotético: realmente estoy creando un archivo tar a partir del código de otra persona, que contiene un nombre de archivo con barras invertidas en el nombre, así es como lo descubrí.)Prueba esto:
Que estaba tratando de usar
find
a-exec tar
. Pero la forma en que funciona la-exec
opción, ejecuta ese comando una vez para cada archivo coincidente que encuentra, haciendotar
que se sobrescriba el archivo tar que produce cada vez. Es por eso que solo terminaste con el último. Además, debe poner comillas alrededor del patrón que especifique parafind
que el shell no lo expanda antes de pasarlofind
.Usando la sustitución de comandos con backticks (o usando la
$(...)
notación si lo prefiere), la lista completa de nombres producidos porfind
se vuelve a pegar en la línea de comandos como argumentostar
, lo que hace que los escriba todos a la vez.fuente
find
rara vez es una buena idea. mywiki.wooledge.org/ParsingLsread -r
de-print0
) como hice en mi respuesta.Pregunta 1
Su comando falla porque
tar
está tomando cada uno de los archivos encontrados y archivándolosfile.tar
. Cada vez que lo haga, sobrescribirá el creado anteriormentefile.tar
.Si lo que desea es un archivo con todos los archivos, simplemente ejecútelo
tar
directamente, no es necesariofind
(y sí, esto funciona para archivos con espacios en sus nombres):Pregunta 2
Los dos comandos son completamente diferentes:
find var / log buscará un directorio llamado
var/log
que es un subdirectorio de su directorio actual , es equivalente afind ./var/log
(observe el./
).find / var / log buscará un directorio llamado
/var/log
que es un subdirectorio de la raíz,/
.El
/
mensaje principal es detar
, nofind
. Significa que está eliminando el primero/
de sus nombres de archivo para convertir las rutas absolutas en relativas . Esto significa que el archivo/var/log/anaconda.error
se extraerá./var/log/anaconda.error
cuando desempaquete el archivo.fuente
Hay dos formas de
-exec
trabajar. Una forma ejecuta el comando muchas veces, una vez para cada archivo; la otra forma ejecuta el comando una vez, incluidos todos los archivos como una lista de parámetros.-exec tar -cvf file.tar {} ';'
ejecuta eltar
comando para cada archivo, sobrescribiendo el archivo cada vez.-exec tar -cvf file.tar {} '+'
ejecuta eltar
comando una vez, creando un archivo de todos los archivos encontrados.fuente
Creo que usar -exec para cada archivo puede hacer que la compresión de tar sea muy lenta, si tienes muchos archivos. Prefiero usar el comando:
fuente
/bin/cpio: xxx: Cannot open: Too many open files