¿Cómo puedo tar un directorio de archivos y carpetas sin incluir el directorio en sí?

StackOverflow https://stackoverflow.com/questions/939982

  •  06-09-2019
  •  | 
  •  

Pregunta

Normalmente hago:

tar -czvf my_directory.tar.gz my_directory

¿Qué pasa si sólo quiero incluir todo (incluidos los archivos ocultos del sistema) en mi_directorio, pero no el directorio en sí?No quiero:

my_directory
   --- my_file
   --- my_file
   --- my_file

Deseo:

my_file
my_file
my_file
¿Fue útil?

Solución

cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd - 

debe hacer el trabajo en una línea. Funciona bien para los archivos ocultos también. "*" No se expande archivos ocultos por la expansión de nombre de ruta al menos en bash. A continuación se muestra mi experimento:

$ mkdir my_directory
$ touch my_directory/file1
$ touch my_directory/file2
$ touch my_directory/.hiddenfile1
$ touch my_directory/.hiddenfile2
$ cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd ..
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2
$ tar ztf my_dir.tgz
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2

Otros consejos

Utilice el interruptor -C de alquitrán:

tar -czvf my_directory.tar.gz -C my_directory .

El -C my_directory le dice a tar para cambiar el directorio actual a my_directory, y luego . significa "poner todo el directorio actual" (incluyendo los archivos ocultos y subdirectorios).

Asegúrese de hacer -C my_directory antes de hacer . o de lo contrario obtendrá los archivos en el directorio actual.

También puede crear archivos como de costumbre y extraerlo con:

tar --strip-components 1 -xvf my_directory.tar.gz

Tener un vistazo a --transform / --xform, le da la oportunidad para masajear el nombre de archivo que el archivo se añade al archivo:

% mkdir my_directory
% touch my_directory/file1
% touch my_directory/file2
% touch my_directory/.hiddenfile1
% touch my_directory/.hiddenfile2
% tar -v -c -f my_dir.tgz --xform='s,my_directory/,,' $(find my_directory -type f)
my_directory/file2
my_directory/.hiddenfile1
my_directory/.hiddenfile2
my_directory/file1
% tar -t -f my_dir.tgz 
file2
.hiddenfile1
.hiddenfile2
file1

Transformar expresión es similar a la de sed, y podemos usar separadores distintos de / (, en el ejemplo anterior).
https://www.gnu.org/software/tar/manual/html_section /tar_52.html

TL; DR

find /my/dir/ -printf "%P\n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

Con algunas condiciones (sólo archivar los archivos, directorios y enlaces simbólicos):

find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

Explicación

La continuación por desgracia incluye un ./ directorio padre en el archivo:

tar -czf mydir.tgz -C /my/dir .

Puede mover todos los archivos de ese directorio utilizando la opción de configuración --transform, pero eso no quiere deshacerse del directorio . sí. Se vuelve cada vez más difícil de dominar el comando.

Se puede usar $(find ...) añadir una lista de archivos para el comando (como en magnus' respuesta ), pero que potencialmente produce un error de una "lista de archivos demasiado tiempo". La mejor manera es combinarlo con la opción -T de alquitrán, así:

find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

Básicamente lo que hace es la lista de todos los archivos (-type f), enlaces (-type l) y subdirectorios (-type d) bajo su directorio, hacer que todos los nombres de archivo relativa utilizando -printf "%P\n", y luego pasar eso al comando tar (se necesitan los nombres de archivo de STDIN usando -T -). Se necesita la opción de modo de alquitrán -C sabe dónde están ubicados los archivos con nombres relativos. La bandera --no-recursion es por lo que el alquitrán no es recursivo en carpetas que se le dice al archivo (causando archivos duplicados).

Si necesita hacer algo especial con los nombres de archivo (filtrado, siguiendo los enlaces simbólicos, etc), el comando find es muy poderoso, y usted puede comprobarlo sólo la eliminación de la parte tar del comando anterior:

$ find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d
> textfile.txt
> documentation.pdf
> subfolder2
> subfolder
> subfolder/.gitignore

Por ejemplo, si desea filtrar los archivos PDF, añadir ! -name '*.pdf'

$ find /my/dir/ -printf "%P\n" -type f ! -name '*.pdf' -o -type l -o -type d
> textfile.txt
> subfolder2
> subfolder
> subfolder/.gitignore

No-GNU encontrar

El comando utiliza printf (disponible en find GNU) que cuenta find para imprimir sus resultados con las rutas relativas. Sin embargo, si usted no tiene find GNU, esto funciona para hacer las rutas relativas (elimina los padres con sed):

find /my/dir/ -type f -o -type l -o -type d | sed s,^/my/dir/,, | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

Esta respuesta debería funcionar en la mayoría de las situaciones.Sin embargo, observe cómo se almacenan los nombres de los archivos en el archivo tar como, por ejemplo, ./file1 en lugar de solo file1.Descubrí que esto causaba problemas al utilizar este método para manipular archivos comprimidos utilizados como archivos de paquete en Construir raíz.

Una solución es utilizar algunos globos Bash para enumerar todos los archivos excepto .. como esto:

tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *

Este es un truco del que aprendí esta respuesta.

Ahora tar devolverá un error si no hay archivos que coincidan ..?* o .[^.]* , pero seguirá funcionando.Si el error es un problema (estás comprobando el éxito en un script), esto funciona:

shopt -s nullglob
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
shopt -u nullglob

Aunque ahora estamos jugando con las opciones del shell, podríamos decidir que es mejor tener * coincidir con archivos ocultos:

shopt -s dotglob
tar -C my_dir -zcvf my_dir.tar.gz *
shopt -u dotglob

Es posible que esto no funcione donde su caparazón brilla * en el directorio actual, por lo que, alternativamente, utilice:

shopt -s dotglob
cd my_dir
tar -zcvf ../my_dir.tar.gz *
cd ..
shopt -u dotglob
cd my_directory
tar zcvf ../my_directory.tar.gz *

Si se trata de un sistema Unix / Linux, y se interesa por los archivos ocultos (que se pierden por *), que tiene que hacer:

cd my_directory
tar zcvf ../my_directory.tar.gz * .??*

No sé qué archivos ocultos se ven como en Windows.

Me gustaría proponer la siguiente función Bash (primer argumento es la ruta a la dir, segundo argumento es el nombre base del archivo resultante):

function tar_dir_contents ()
{
    local DIRPATH="$1"
    local TARARCH="$2.tar.gz"
    local ORGIFS="$IFS"
    IFS=$'\n'
    tar -C "$DIRPATH" -czf "$TARARCH" $( ls -a "$DIRPATH" | grep -v '\(^\.$\)\|\(^\.\.$\)' )
    IFS="$ORGIFS"
}

Se puede ejecutar de esta manera:

$ tar_dir_contents /path/to/some/dir my_archive

y generará la my_archive.tar.gz archivo dentro del directorio actual. Funciona con elementos ocultos (. *) Y con elementos con espacios en su nombre de archivo.

cd my_directory && tar -czvf ../my_directory.tar.gz $(ls -A) && cd ..

Éste trabajó para mí y es incluir todos los archivos ocultos sin poner todos los archivos en un directorio raíz denominada "" Al igual que en de Tomoe respuesta :

Uso pax.

Pax es un paquete obsoleto, pero hace el trabajo perfectamente y de forma sencilla.

pax -w > mydir.tar mydir

La manera más sencilla que he encontrado:

cd mi_dir && tar -czvf ../my_dir.tar.gz *

# tar all files within and deeper in a given directory
# with no prefixes ( neither <directory>/ nor ./ )
# parameters: <source directory> <target archive file>
function tar_all_in_dir {
    { cd "$1" && find -type f -print0; } \
    | cut --zero-terminated --characters=3- \
    | tar --create --file="$2" --directory="$1" --null --files-from=-
}

maneja de forma segura los nombres de archivo con espacios u otros caracteres inusuales. Se pueden añadir opcionalmente un -name '*.sql' o un filtro similar al comando find para limitar los archivos incluidos.

 tar -cvzf  tarlearn.tar.gz --remove-files mytemp/*

Si la carpeta está mytemp continuación, si se aplica lo anterior será comprimir y eliminar todos los archivos de la carpeta, pero no lo toque

 tar -cvzf  tarlearn.tar.gz --remove-files --exclude='*12_2008*' --no-recursion mytemp/*

Puede dar excluye los patrones y también especificar que no se vea demasiado en subcarpetas

tar -C my_dir -zcvf my_dir.tar.gz `ls my_dir`
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top