solo archivos tar, no hay directorios

16

Probablemente pueda escribir un script de shell para buscar solo archivos, luego pasar la lista a tar, pero me pregunto si ya hay una característica incorporada en tar que permita hacer eso, en una sola línea de comando.

Por ejemplo, encontré el --no-recursioninterruptor, pero cuando lo hago:

tar --no-recursion -cvf mydir.tar mydir

Solo archiva los nombres de las entradas en el directorio (¡incluidos los subdirectorios!), Pero no archiva ningún archivo.

También probé:

 tar --no-recursion -cvf mydir.tar mydir/*

Pero aunque solo archiva archivos, también archiva los nombres de los subdirectorios.

¿Hay alguna manera de decirle a los archivos tar solamente, sin directorios?

ateiob
fuente
55
Solo para aclarar: ¿desea crear un archivo con estructura "plana" (es decir, todos los archivos mezclados en un directorio)?
rozcietrzewiacz
1
Podría crear un nuevo directorio find mydir -type f |xargs cp -t tempdiry luego tar tempdir.
Kevin
@rozcietrzewiacz Sí, plano, pero solo desde ese directorio, no desde subdirectorios.
ateiob
1
OK, creo que veo lo que intentas hacer. ¿Qué talfind mydir -depth 1 -type f | xargs tar cf mydir.tar
Kevin
2
Ah, espacios. Uso hallazgo es -exec lugar: find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +. El +pone todos los archivos en la misma línea de comando como xargs.
Kevin

Respuestas:

11

Como señala Camh, el comando anterior tenía un pequeño problema en el sentido de que dado demasiados nombres de archivo, se ejecutaría más de una vez, con invocaciones posteriores que borraban silenciosamente las ejecuciones anteriores. Como tampoco estamos comprimiendo, podemos agregar en lugar de sobrescribir:

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar Avf mydir.tar
find mydir -maxdepth 1 -type f -exec tar Avf mydir.tar {} +

La respuesta de Iocnarz de usar tar's --nully -Topciones también funciona. Si lo ha cpioinstalado, la respuesta de Camh al usarlo también está bien. Y si tiene zshy no le importa usarlo para un comando, la respuesta de Gilles usando un zsh glob ( *(.)) parece la más sencilla.


La clave era la -maxdepthopción. Respuesta final, lidiando con espacios adecuadamente

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar cvf mydir.tar

Esto también debería funcionar:

find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +
Kevin
fuente
44
Ambos pueden resultar en múltiples invocaciones de tar. Ambos xargsy findcon la +variante tienen un número máximo de argumentos que se pueden pasar a tar. Esto dará como resultado que la segunda invocación de tar sobrescriba la salida de la primera.
camh
2
Al expandirse en el límite de xargs, xargs se predetermina a una línea de comando máxima de 128 KB. Si la lista de archivos es más grande, obtiene una segunda (o más) invocación del comando (tar), lo que lleva a una pérdida silenciosa de datos. Puede usar -xpara forzar a los xargs a fallar en lugar de perder datos, y aunque es mejor que un error de pérdida de datos silencioso, aún no es ideal. Este error de clasificación es muy peligroso porque todo parece estar bien al principio, pero a medida que la lista de archivos crece con el tiempo, comienzas a activarlo y es posible que no lo notes hasta que intentes restaurar tu copia de seguridad. Entonces es muy tarde.
camh
@camh Tienes razón, gracias por señalarlo; He actualizado para reflejar eso.
Kevin
1
La "respuesta final" no es correcta, si usa "tar c" sin -T puede obtener resultados parciales.
eckes
14

Cuando quiera usar findcon tar, la mejor manera es usar en cpiolugar de tar. cpiopuede escribir archivos tar y está diseñado para tomar la lista de archivos para archivar desde stdin.

find mydir -maxdepth 1 -type f -print0 | cpio -o -H ustar -0 > mydir.tar

El uso de findy cpioes un enfoque más unix-y en el que permite findhacer la selección de archivos con toda la potencia que tiene, y permite cpiorealizar el archivo. Vale la pena aprender este uso simple cpio, ya que le resulta fácil resolver los problemas con los que golpea su ventaja cuando lo intenta tar.

camh
fuente
¡Brillante! He usado cpio en el pasado distante, pero nunca supe de la opción ustar.
Ian McGowan
2
Esto funcionó mucho mejor para mí que la respuesta aceptada.
Dale Anderson
1
solo una liendre el -maxdepth 1 debería aparecer antes del -tipo f o recibirás una advertencia de algunos hallazgos
kdubs
Gracias @ kdubs. He actualizado la respuesta para poner -maxdepthantes -type.
camh
3

No estoy seguro de entender sus requisitos. Si desea almacenar los archivos regulares mydirpero no sus subdirectorios, la forma más fácil es usar zsh, donde solo los archivos regulares coincidentes son la simple cuestión de usar el . calificador glob :

tar cf mydir.tar mydir/*(.)
Gilles 'SO- deja de ser malvado'
fuente
3

Incluso puede usar find ... -print0y tar ... --nulldirectamente sin usar xargsen absoluto.

find . -maxdepth 1 -type f -print0 | tar cvf mydir.tar --null -T -

En el ejemplo dado, la --no-recursionopción a tarno es necesaria porque solo las rutas de los archivos (y no los directorios) se pasarán de finda tar.

Sin embargo, el uso de la --no-recursionopción taren el siguiente ejemplo evita el tardoble archivo de directorios. findhará la recursión del árbol de directorios en lugar de tarentonces.

# compare
find . -print0 | tar cf mydir.tar --null -T -
tar -tf mydir.tar | nl

find . -print0 | tar cf mydir.tar --null --no-recursion -T -
tar -tf mydir.tar | nl
locnarz
fuente
2

Como man tardice el párrafo introductorio en (última oración),

El uso de un nombre de directorio siempre implica que los subdirectorios a continuación deben incluirse en el archivo.

Lo cual entiendo como un "no" a su pregunta.

rozcietrzewiacz
fuente
Buena captura, excepto que el alquitrán ahora incluye numerosos mecanismos de exclusión (p --no-recursion. Ej . --exclude-tag, Etc.). Estoy investigando lo --exclude-tagque parece prometedor, pero parece ser exactamente lo contrario de lo que estoy buscando.
ateiob
Intenté esto y vi que se eliminaban caracteres de los nombres de ruta largos. El uso de alquitrán con -T y --null como propuso camh evitó este problema.
Paul Brannan
1
star -c -C startdir -find . ! -type d > out.tar

Omita -C startdiry reemplace .con startdirsi debería aparecer en el archivo.

Este es el método más eficiente basado en las características de libfind. Libfind también ofrece primarios -chown -chgrp -chmodque modifican las estadísticas de estructura en su lugar y permiten archivar diferentes metadatos. Esto también funciona en modo de lista y extracción y evita la necesidad de extraer todo el archivo en muchos casos.

astuto
fuente
¿Se puede usar -finden -copymodo? La sinopsis de la página de manual sugiere que puede hacerlo, pero no he podido hacerlo funcionar (al intentar responder Cómo copiar archivos modificados mientras se preserva la estructura de carpetas ) (con schily-2016-02-10)
Stéphane Chazelas
No probé esto por más tiempo. Puede ser que actualmente haya un error. La página de manual dice que el último argumento sería el directorio de extracción, pero cuando intento esto, obtengo: "Los argumentos de ruta aún no son compatibles en el modo de extracción". ¿Es esto lo que obtienes cuando lo intentas?
schily
si. La página de manual también dice que solo puede haber argumentos de búsqueda después de -find, pero si pongo el directorio de destino antes de -find también obtengo un error
Stéphane Chazelas
Hay un código para desactivar el código de búsqueda en el proceso de extracción y el mensaje de error proviene de una verificación incorrecta que espera -c pero también debe permitir -copy. En modo copia, el analizador de búsqueda no debe incluir el último argumento.
schily
1
Ahora se ha publicado una solución final en las herramientas de schily en sourceforge.net/projects/schilytools/files/schily-2016-03-11.tar.bz2, esto también soluciona un problema de una falta de setlocale () en estrella y esto permite: C directriz para star -find.
schily
0

Podría haber encontrado una solución.

find mydir -type f -printf '%P\0'|tar czvf mydir.tar.gz -C mydir --null -T -

Esto puede ser un poco costoso, pero de todos modos funcionará, porque esto no depende de los xargs.

ciel
fuente
-1

dir = your_dir; cd $ dir; tar -cvf file.tar `buscar. -maxdepth 1 -type f -print`

H Bosch
fuente