Tar un directorio, pero no almacene rutas absolutas completas en el archivo


277

Tengo el siguiente comando en la parte de un script de shell de respaldo:

tar -cjf site1.bz2 /var/www/site1/

Cuando enumero el contenido del archivo, obtengo:

tar -tf site1.bz2
var/www/site1/style.css
var/www/site1/index.html
var/www/site1/page2.html
var/www/site1/page3.html
var/www/site1/images/img1.png
var/www/site1/images/img2.png
var/www/site1/subdir/index.html

Pero me gustaría eliminar la parte /var/www/site1del directorio y los nombres de archivo dentro del archivo, para simplificar la extracción y evitar una estructura de directorio constante inútil. Nunca se sabe, en caso de que extraiga sitios web respaldados en un lugar donde no se almacenaron los datos web /var/www.

Para el ejemplo anterior, me gustaría tener:

tar -tf site1.bz2
style.css
index.html
page2.html
page3.html
images/img1.png
images/img2.png
subdir/index.html

Entonces, cuando extraigo, los archivos se extraen en el directorio actual y no necesito mover los archivos extraídos después, y así se preservan las estructuras del subdirectorio.

Ya hay muchas preguntas sobre el alquitrán y la copia de seguridad en stackoverflowy en otros lugares de la web, pero la mayoría de ellas solicitan que se elimine toda la estructura del subdirectorio (aplanamiento), o simplemente agregue o elimine la inicial / en los nombres (no lo hago ' No sé qué cambia exactamente cuando se extrae), pero no más.

Después de leer algunas de las soluciones encontradas aquí y allá, así como el manual, probé:

tar -cjf site1.bz2 -C . /var/www/site1/
tar -cjf site1.bz2 -C / /var/www/site1/
tar -cjf site1.bz2 -C /var/www/site1/ /var/www/site1/
tar -cjf site1.bz2 --strip-components=3 /var/www/site1/

Pero ninguno de ellos funcionó como yo quiero. Algunos no hacen nada, otros ya no archivan subdirectorios.

Está dentro de un script de shell de respaldo lanzado por un Cron, por lo que no sé bien, qué usuario lo ejecuta, cuál es la ruta y el directorio actual, por lo que siempre se requiere escribir una ruta absoluta para todo, y preferiría no cambiar el directorio actual para evitar romper algo más en el script (porque no solo respalda sitios web, sino también bases de datos, luego envía todo eso a FTP, etc.)

¿Cómo lograr esto?

¿Acabo de entender mal cómo funciona la opción -C?



Bueno, -Csolo significa "cambiar directorio", mientras que la sustitución de una ruta (o prefijo) solo puede hacerse mediante --transform. rif. superuser.com/questions/595510/prepend-prefix-in-tar/595512 puede simplemente -C (cambiar directorio) y --transformarlo: `` `tar cjf site1.bz2 --transform" s / ^ \. \ // $ targetbase / "-C / var / www / site1. ``
Daniele Cruciani

Esta es una muy buena pregunta y lamentablemente ninguna de las respuestas a esta fecha es satisfactoria. Todavía tenemos que escuchar de alguna persona sabia cómo podríamos extraer solo el archivo style.css (ejemplo anterior) en el directorio actual sin ninguna referencia a la ubicación original o al árbol de directorios. No quiero saturar mi directorio actual con una nueva estructura de árbol no deseada. Suena como una grave deficiencia del tarball que ha sido ignorado durante años.
elmclose

Respuestas:


383
tar -cjf site1.tar.bz2 -C /var/www/site1 .

En el ejemplo anterior, tar cambiará a directorio /var/www/site1antes de hacer lo suyo porque -C /var/www/site1se le dio la opción .

De man tar:

OTHER OPTIONS

  -C, --directory DIR
       change to directory DIR

152
No te pierdas el punto al final, eso es importante ;-)
Freedom_Ben

9
¿qué tal si también desea seleccionar los archivos para hacer una copia de seguridad en función de un comodín? -C / var / www / site1 * .dat no funciona :(
Andy Lorenz

16
El punto le dice tarque archive todo en el directorio actual. Y -Cestablece el directorio actual.
Lars Brinkhoff

21
Esto funciona muy bien. Me resulta útil preservar el nombre del directorio (simplemente no la ruta completa), así que hice lo siguiente: tar -czvf site1.tar.gz -C /var/www/ site1(Tenga en cuenta el espacio, todavía estoy usando -C, para cd al directorio padre y especificando el directorio a tar en lugar de punto)
jorfus

9
Obtengo un punto inicial en la ruta del alquitrán, por ejemplo, ./folders¿cómo se puede eliminar?
Mika571

39

La opción -Cfunciona; solo para aclarar, publicaré 2 ejemplos:

  1. creación de un tarball sin la ruta completa: ruta completa /home/testuser/workspace/project/application.wary lo que queremos es simplemente project/application.warasí:

    tar -cvf output_filename.tar  -C /home/testuser/workspace project

    Nota: hay un espacio entre workspacey project; tar reemplazará la ruta completa con solo project.

  2. extracción de tarball con el cambio de la ruta de destino (por defecto ., es decir, el directorio actual)

    tar -xvf output_filename.tar -C /home/deploy/

    tarextraerá tarball en función de la ruta dada y preservará la ruta de creación; en nuestro ejemplo el archivo application.warserá extraído a /home/deploy/project/application.war.

    /home/deploy: dado en extracto
    project: dado en la creación de tarball

Nota: si desea colocar el tarball creado en un directorio de destino, simplemente agregue la ruta de destino antes del nombre del tarball. p.ej:

tar -cvf /path/to/place/output_filename.tar  -C /home/testuser/workspace project

1
¿Cómo agregar comodines para la selección de archivos en el último ejemplo?
Siva

El problema con los comodines es que el shell los expande a los nombres de archivo coincidentes y que tar no los expande si se citan ...
Gert van den Berg

Probé esto en Ubuntu 18.04 y no tuve suerte. No estoy seguro de lo que me estoy perdiendo. Mi stdout lo muestra correctamente cuando lo empaqueto, pero cuando lo descomprimo, todavía tiene la ruta completa
sdc

14

Parece que la -Copción upto tar v2.8.3 no funciona de manera consistente en todas las plataformas (SO). -CSe dice que la opción agrega un directorio al archivo, pero en Mac y Ubuntu agrega el prefijo de ruta absoluta dentro del archivo tar.gz generado.

tar target_path/file.tar.gz -C source_path/source_dir

Por lo tanto, la solución consistente y robusta es cdingresar a source_path (directorio padre de source_dir) y ejecutar

tar target_path/file.tar.gz source_dir

o

tar -cf target_path/file.tar.gz source_dir

en tu guion Esto eliminará el prefijo de ruta absoluta en la estructura de directorio de su archivo tar.gz generado.


1
El uso de la opción -C DID eliminar los prefijos de ruta absolutos dentro del archivo tar.gz generada en Fedora 29. ¿Es su respuesta específica a algún sistema?
EL_DON

@EL_DON: No probé la opción -C en Fedora, pero idealmente el software de la aplicación tar debería funcionar de manera consistente en todas las plataformas a menos que sea un error en la aplicación tar. -C opción, probé en Mac 10.8 y Mac 10.13 y Ubuntu (versión que no recuerdo). Pero a partir de tar v2.8.3, el comando se ha cambiado a tar -cf target_path / file.tar.gz source_dir y, si agrega la opción -C, no eliminará el prefijo de ruta absoluta dentro del archivo tar.gz generado.
Chinthaka Senanayaka

Probé nuevamente en un sistema centOS. Después de crear todas las rutas en el ejemplo y ejecutar el comando (con -cvfagregado después tar), encuentro que el archivo tar.gz resultante no tiene rutas absolutas dentro de él, lo que es consistente con varias otras respuestas. Si cree que el alquitrán está roto o desactualizado en los dos sistemas que he usado para las pruebas, enlace a alguna documentación que respalde su respuesta. Creo que la -Copción cambia el directorio antes de ejecutar (como en otras respuestas). Cuando lo omito, tar intenta agregar basura desde ./, incluidas las rutas de inicio ./.
EL_DON

Usé este documento: linux.die.net/man/1/tar Sí, el documento dice que -C haría el cambio de ruta, pero en mi Mac 10.13 no funciona. Esto puede ser un comportamiento inconsistente de la aplicación tar. Eso significa que esto es un error. Si está escribiendo un script de shell para ejecutar en todas las plataformas de Unix, entonces es mejor estar seguro con el código de ejecución que funcionará en todos los sistemas operativos.
Chinthaka Senanayaka

Su respuesta no dice que puede haber un error y la solución más sólida para la compatibilidad multiplataforma es cdprimero. Su respuesta dice que la herramienta funciona de la manera opuesta a cómo los documentos dicen que funciona y cómo funciona en mi sistema, por lo que es una respuesta incorrecta. Podrías arreglarlo fácilmente.
EL_DON

7

El siguiente comando creará un directorio raíz "." y poner todos los archivos del directorio especificado en él.

tar -cjf site1.tar.bz2 -C /var/www/site1 .

Si desea colocar todos los archivos en la raíz del archivo tar, @chinthaka está en lo cierto. Simplemente cd en el directorio y hacer:

tar -cjf target_path/file.tar.gz *

Esto colocará todos los archivos en el cwd en el archivo tar como archivos raíz.


1
El uso de * no guarda ningún archivo "oculto" o carpeta. (para su información, el uso de -C junto con * falla, el shell expande el directorio actual, no el directorio -C)
Xen2050

1

Usar el "punto" lleva a la creación de una carpeta llamada "punto" (en Ubuntu 16).

tar -tf site1.bz2 -C /var/www/site1/ .

Me ocupé de esto con más detalle y preparé un ejemplo. Grabación multilínea, más una excepción.

tar -tf site1.bz2\
    -C /var/www/site1/ style.css\
    -C /var/www/site1/ index.html\
    -C /var/www/site1/ page2.html\
    -C /var/www/site1/ page3.html\
    --exclude=images/*.zip\
    -C /var/www/site1/ images/
    -C /var/www/site1/ subdir/
/

¿Por qué lo llamas "punto"? Es solo ., que es el directorio actual. En el contexto de la tar.gzestructura de 's, eso es solo el nivel base / raíz / superior, ¿verdad?
EL_DON

Vea la instantánea para la imagen de detalles . Mi manera es más correcta de usar, es mi opinión.
Sergey Asachev

0

Si desea archivar un subdirectorio y recortar la ruta del subdirectorio, este comando será útil:

tar -cjf site1.bz2 -C /var/www/ site1
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.