tar: agregue todos los archivos y directorios en el directorio actual INCLUYENDO .svn y así sucesivamente


90

Intento tar.gz en un directorio y uso

tar -czf workspace.tar.gz *

El tar resultante incluye .svndirectorios en subdirectorios pero NO en el directorio actual (ya que *se expande a solo archivos 'visibles' antes de pasar a tar

lo intenté

tar -czf workspace.tar.gz .en su lugar, pero luego recibo un error porque '.' ha cambiado durante la lectura:

tar: ./workspace.tar.gz: file changed as we read it

¿Hay algún truco para que *coincida con todos los archivos (incluidos los con prefijo de punto) en un directorio?

(usando bash en Linux SLES-11 (2.6.27.19)


5
¿Quizás esta pregunta pertenece al superusuario?
Peter Jaric

Respuestas:


76

No cree el archivo tar en el directorio que está empaquetando:

tar -czf /tmp/workspace.tar.gz .

hace el truco, excepto que extraerá los archivos en todo el directorio actual cuando desempaquete. Mejor hacer:

cd ..
tar -czf workspace.tar.gz workspace

o, si no conoce el nombre del directorio en el que se encontraba:

base=$(basename $PWD)
cd ..
tar -czf $base.tar.gz $base

(Esto supone que no siguió enlaces simbólicos para llegar a donde está y que el shell no intenta adivinarlo saltando hacia atrás a través de un enlace simbólico; bashno es confiable en este sentido. Si tiene que preocuparse por eso, usar cd -P ..para hacer un directorio de cambios físicos. Es estúpido que no sea el comportamiento predeterminado en mi opinión, confuso, al menos, para aquellos para quienes cd ..nunca tuvo un significado alternativo).


Un comentario en la discusión dice:

Necesito [...] excluir el directorio superior y necesito [...] colocar el tar en el directorio base.

La primera parte del comentario no tiene mucho sentido: si el archivo tar contiene el directorio actual, no se creará cuando extraiga el archivo de ese archivo porque, por definición, el directorio actual ya existe (excepto en circunstancias muy extrañas ).

La segunda parte del comentario se puede tratar de dos formas:

  1. O bien: cree el archivo en otro lugar, /tmpes una ubicación posible, y luego muévalo a la ubicación original una vez que esté completo.
  2. O: si está usando GNU Tar, use la --exclude=workspace.tar.gzopción. La cadena después de =es un patrón, el ejemplo es el patrón más simple, una coincidencia exacta. Es posible que deba especificar --exclude=./workspace.tar.gzsi está trabajando en el directorio actual en contra de las recomendaciones; es posible que deba especificar --exclude=workspace/workspace.tar.gzsi está subiendo un nivel como se sugiere. Si tiene varios archivos tar para excluir, use ' *', como en --exclude=./*.gz.

1
Buena respuesta, pero tengo una situación en la que me veo obligado a ejecutar este comando dentro del directorio que debe empaquetarse. No tengo permisos suficientes para ejecutarlo en el exterior.
Hexodus

Un lugar perfecto para empacar es / tmp seguro.
Andre Fellows

46

Si realmente no desea incluir el directorio superior en el tarball (y eso generalmente es una mala idea):

tar czf workspace.tar.gz -C /path/to/workspace .

Necesito excluir el directorio superior y necesito colocar el tar en el directorio base.
Micha

@Micha crea un script bash para archivar y copiar el archivo después
Fedir RYKHTIK

2
Te estás perdiendo el - en -czf, creo.
UpTheCreek

10
man tar: El primer argumento de tar debería ser una función; una de las letras Acdrtuxo uno de los nombres largos de función. Una letra de función no necesita tener el prefijo- y puede combinarse con otras opciones de una sola letra.
rkhayrov

4
Todavía no funciona, todavía tengo el "." como directorio superior en mi tarball
A. Gille

43

Hay un par de pasos a seguir:

  1. Reemplazar *por .para incluir archivos ocultos también.
  2. Para crear el archivo en el mismo directorio, --exclude=workspace.tar.gzse puede utilizar un para excluir el archivo en sí.
  3. Para evitar el tar: .: file changed as we read iterror cuando el archivo aún no se ha creado, asegúrese de que exista (por ejemplo, usando touch), de modo que --exclude coincida con el nombre del archivo. (No coincide con el archivo no existe)

Combinado, esto da como resultado el siguiente script:

touch workspace.tar.gz
tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

7
Leí todas las respuestas y comentarios y esta es la mejor manera de crear tarball en el mismo directorio. De esta respuesta también entendí por qué ocurre este error.
Szymon Sadło

Si desea ver el progreso mientras se está comprimiendo el archivo de alquitrán, se puede añadir una bandera adicional para --verbose, de este modo: -czvf.
Mastrianni

18

en el directorio desea comprimir (directorio actual) intente esto:

tar -czf workspace.tar.gz . --exclude=./*.gz

2
Pero ahora se queja de que el archivo "." cambiado mientras se lee. ¿Puedo estar seguro de que se han incluido todos los archivos?
Jaan

1
Esto excluye todos los .gzarchivos del directorio.
omerfarukdogan

12

Puede incluir los directorios ocultos retrocediendo un directorio y haciendo:

cd ..
tar czf workspace.tar.gz workspace

Suponiendo que el directorio que deseaba gzip se llamara espacio de trabajo.


Y esto también evita el problema del cambio de archivo.
Jonathan Leffler

No funciona cuando el usuario no tiene permiso de escritura en la carpeta principal.
Joachim Wagner

Exactamente @JoachimWagner!
p01ymath

1
@JoachimWagner. Si no tiene permiso de escritura, cámbielo a:tar -czf /path/to/where/you/do/have/permission/workspace.tar.gz workspace
bramp

1
Tuve que sacar -antes del czfpara que funcionara. De lo contrario, recibí un Cannot stat: No such file or directorymensaje de error.
Phemelo Khetho

6

Puede arreglar el .formulario usando --exclude:

tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

5

Actualización: agregué una solución para el comentario del OP.

tar -czf workspace.tar.gz .

de hecho cambiará el directorio actual, pero ¿por qué no colocar el archivo en otro lugar?

tar -czf somewhereelse/workspace.tar.gz .
mv somewhereelse/workspace.tar.gz . # Update

El archivo se procesará posteriormente y se requiere que esté en el espacio de trabajo; es un poco feo, pero solo es necesario (todo es solo una solución ...)
Micha

OK, agregaré una solución para eso :)
Peter Jaric

Y si necesita poder ejecutar esto repetidamente, agregue 'rm workspace.tar.gz' antes de la línea tar.
Peter Jaric

Si desea tar un disco completo, en el mismo disco, parece que no tiene muchas opciones.
BeeOnRope

4

En realidad, el problema está en las opciones de compresión. El truco consiste en enviar el resultado del alquitrán a un compresor en lugar de utilizar las opciones integradas. Por cierto, eso también puede brindarle una mejor compresión, ya que puede establecer opciones de compresión adicionales.

Alquitrán mínimo:

tar --exclude=*.tar* -cf workspace.tar .

Tubería a un compresor de su elección. Este ejemplo es detallado y usa xz con máxima compresión:

tar --exclude=*.tar* -cv . | xz -9v >workspace.tar.xz

La solución se probó en Ubuntu 14.04 y Cygwin en Windows 7. Es una respuesta de la wiki de la comunidad, así que no dude en editarla si detecta un error.


¡Gracias! Salvé mi vida
Steven

2

El problema con la mayoría de las soluciones proporcionadas aquí es que tar contiene ./al principio de cada entrada. Entonces, esto da como resultado tener un .directorio al abrirlo a través del compresor GUI. Entonces, lo que terminé haciendo es:

ls -1A | xargs -d "\n" tar cfz my.tar.gz

Si ya lo tiene my.tar.gzen el directorio actual, es posible que desee eliminar esto:

ls -1A | grep -v my.tar.gz | xargs -d "\n" tar cfz my.tar.gz

Tenga en cuenta que xargs tiene cierto límite (ver xargs --show-limits). Entonces, esta solución no funcionaría si está tratando de crear un paquete que tiene muchas entradas (directorios y archivos) en un directorio que está tratando de tar.


1

Buena pregunta. En ZSH puede usar el modificador globbing (D), que significa "dotfiles". Comparar:

ls $HOME/*

y

ls $HOME/*(D)

Esto excluye correctamente las entradas especiales del directorio .y ... En Bash puede usar .*para incluir los archivos de puntos explícitamente:

ls $HOME/* $HOME/.*

Pero eso incluye .y ..también, así que no es lo que estabas buscando. Estoy seguro de que también hay alguna forma de hacer *coincidir los archivos de puntos en bash.


En bash, use .??*para hacer coincidir todos los archivos dot no .y ... Eso no obtiene archivos de puntos de un solo carácter (como .a). Para obtenerlos también, use el más complicado .[^.]*.
Scott Minster

1

Otra solución más, asumiendo que la cantidad de elementos en la carpeta no es enorme:

tar -czf workspace.tar.gz `ls -A`

( ls -Aimprime archivos normales y ocultos pero no "." y ".." como lo ls -ahace).


0
tar -czf workspace.tar.gz .??* *

La especificación .??*incluirá archivos y directorios con "puntos" que tengan al menos 2 caracteres después del punto. El lado negativo es que no incluirá archivos / directorios con un solo carácter después del punto, por ejemplo .a, si hay alguno.


0

Si el espacio en el disco no es un problema, esto también podría ser algo muy fácil de hacer:

mkdir backup
cp -r ./* backup
tar -zcvf backup.tar.gz ./backup

0

Yo mismo tuve una situación similar. Creo que es mejor crear el tar en otro lugar y luego usar -C para decirle a tar el directorio base para los archivos comprimidos. Ejemplo:

tar -cjf workspace.tar.gz -C <path_to_workspace> $(ls -A <path_to_workspace>)

De esta forma, no es necesario excluir su propio archivo tar. Como se señaló en otros comentarios, -A enumerará los archivos ocultos.


0

10 años después, tiene una alternativa a tar, ilustrada con Git 2.30 (Q1 2021), que usa " git archive" ( man ) para producir el tarball de lanzamiento en lugar de tar.
(No necesita Git 2.30 para aplicar esa alternativa)

Consulte la confirmación 4813277 (11 de octubre de 2020) y la confirmación 93e7031 (10 de octubre de 2020) de René Scharfe ( rscharfe) .
(Combinado por Junio ​​C Hamano - gitster- en el compromiso 63e5273 , 27 de octubre de 2020)

Makefile: use git init / add / commit / archive para dist-doc

Firmado por: René Scharfe

Reduzca la dependencia de herramientas externas generando archivos de distribución para documentación HTML y páginas de manual utilizando comandos ( man ) en lugar de tar. Esto le da a las entradas del archivo los mismos metadatos que los del archivo dist para binarios.git

Entonces en lugar de:

tar cf ../archive.tar .

Puedes hacerlo usando solo Git:

git -C workspace init
git -C workspace add .
git -C workspace commit -m workspace
git -C workspace archive --format=tar --prefix=./ HEAD^{tree} > workspace.tar
rm -Rf workspace/.git

Eso se propuso inicialmente porque, como se explica aquí , alguna plataforma exótica podría tener una distribución de alquitrán antigua sin opciones.


-1

Usar findes probablemente la forma más fácil:

find . -maxdepth 1 -exec tar zcvf workspace.tar.gz {} \+

find . -maxdepth 1encontrará todos los archivos / directorios / enlaces simbólicos / etc en el directorio actual y ejecutará el comando especificado por -exec. El {}en el comando significa que la lista de archivos va aquí y \+significa que el comando se ejecutará como:

tar zcvf workspace.tar.gz .file1 .file2 .dir3

en vez de

tar zcvf workspace.tar.gz .file1
tar zcvf workspace.tar.gz .file2
tar zcvf workspace.tar.gz .dir3

-J es --xz en el manual; combinado con -c es solo el comienzo de lo que una computadora llamará "diversión" :)
Ricalsin

Jaja, mi mini-servidor en casa está más limitado por el espacio en disco que por la CPU :) Buen punto; Lo cambiaré para usar gzip.
Andrew Gunnerson
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.