gzip - una - mover varios archivos en linux
¿Cómo puedo crear un directorio de archivos y carpetas sin incluir el directorio? (15)
TL; DR
find /my/dir/ -printf "%P/n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
Con algunas condiciones (archivos de solo archivos, dirs 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
Desafortunadamente, el siguiente incluye un directorio principal ./
en el archivo:
tar -czf mydir.tgz -C /my/dir .
Puede mover todos los archivos fuera de ese directorio utilizando la opción de configuración --transform
, pero eso no elimina los archivos .
directorio en sí. Se vuelve cada vez más difícil domesticar el comando.
Podría usar $(find ...)
para agregar una lista de archivos al comando (como en la respuesta de magnus ), pero eso potencialmente causa un error de "lista de archivos demasiado larga". La mejor manera es combinarlo con la opción -T
de tar, como esta:
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 enumerar todos los archivos ( -type f
), enlaces ( -type l
) y subdirectorios ( -type d
) debajo de su directorio, hacer que todos los nombres de archivo sean relativos usando -printf "%P/n"
, y luego pasarlo a el comando tar (toma los nombres de archivos de STDIN usando -T -
). La opción -C
es necesaria para que tar sepa dónde se encuentran los archivos con nombres relativos. El indicador --no-recursion
es para que tar no se convierta en carpetas que se le ordena archivar (causando archivos duplicados).
Si necesita hacer algo especial con los nombres de archivo (filtrado, seguimiento de enlaces simbólicos, etc.), el comando de find
es bastante poderoso, y puede probarlo simplemente eliminando 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 archivos PDF, agregue ! -name ''*.pdf''
! -name ''*.pdf''
$ find /my/dir/ -printf "%P/n" -type f ! -name ''*.pdf'' -o -type l -o -type d
> textfile.txt
> subfolder2
> subfolder
> subfolder/.gitignore
Hallazgo no GNU
El comando usa printf
(disponible en GNU find
) que le dice a find
que imprima sus resultados con rutas relativas. Sin embargo, si no tiene un buscador GNU, esto funciona para que los caminos sean relativos (elimina a 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 -
Normalmente hago
tar -czvf my_directory.tar.gz my_directory
¿Qué sucede si solo 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
Quiero:
my_file
my_file
my_file
Eche un vistazo a --transform
/ --xform
, le da la oportunidad de dar masajes al nombre del archivo a medida que el archivo se agrega 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
La expresión de transformació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
La forma más sencilla que encontré:
cd my_dir && tar -czvf ../my_dir.tar.gz *
Propondría la siguiente función Bash (el primer argumento es la ruta al directorio, el 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"
}
Puedes ejecutarlo de esta manera:
$ tar_dir_contents /path/to/some/dir my_archive
y generará el archivo my_archive.tar.gz
dentro del directorio actual. Funciona con elementos ocultos (. *) Y con elementos con espacios en su nombre de archivo.
Si se trata de un sistema Unix / Linux, y te preocupan los archivos ocultos (que se perderán *), debes hacerlo:
cd my_directory
tar zcvf ../my_directory.tar.gz * .??*
No sé cómo se ven los archivos ocultos en Windows.
También puede crear el archivo como de costumbre y extraerlo con:
tar --strip-components 1 -xvf my_directory.tar.gz
Utilice el interruptor -C
de tar:
tar -czvf my_directory.tar.gz -C my_directory .
La -C my_directory
le dice a tar que cambie el directorio actual a my_directory
, y luego .
significa "agregar todo el directorio actual" (incluidos los archivos ocultos y los subdirectorios).
Asegúrate de hacer -C my_directory
antes de hacerlo .
o de lo contrario obtendrá los archivos en el directorio actual.
Utilice pax.
Pax es un paquete obsoleto, pero hace el trabajo perfectamente y de manera simple.
pax -w > mydir.tar mydir
share debería funcionar en la mayoría de las situaciones. Sin embargo, ./file1
en cuenta cómo se almacenan los nombres de archivo en el archivo tar como, por ejemplo, ./file1
lugar de solo file1
. Descubrí que esto causaba problemas al usar este método para manipular los archivos BuildRoot utilizados como archivos de paquete en BuildRoot .
Una solución es usar algunos globs de Bash para enumerar todos los archivos excepto para ..
así:
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
Este es un truco que aprendí de esta respuesta .
Ahora tar devolverá un error si no hay archivos que coincidan con ..?*
.[^.]*
, Pero seguirá funcionando. Si el error es un problema (está comprobando el éxito en una secuencia de comandos), esto funciona:
shopt -s nullglob
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
shopt -u nullglob
Aunque ahora estamos jugando con las opciones de shell, podemos decidir que es mejor tener *
coincidir con los archivos ocultos:
shopt -s dotglob
tar -C my_dir -zcvf my_dir.tar.gz *
shopt -u dotglob
Es posible que esto no funcione donde sus globos de shell *
en el directorio actual, por lo tanto, use:
shopt -s dotglob
cd my_dir
tar -zcvf ../my_dir.tar.gz *
cd ..
shopt -u dotglob
tar -cvzf tarlearn.tar.gz --remove-files mytemp/*
Si la carpeta es mytemp, si aplica lo anterior, se comprimirán y eliminarán todos los archivos de la carpeta, pero no la toque.
tar -cvzf tarlearn.tar.gz --remove-files --exclude=''*12_2008*'' --no-recursion mytemp/*
Puede dar patrones de exclusión y también especificar no mirar las subcarpetas también
cd my_directory
tar zcvf ../my_directory.tar.gz *
cd my_directory && tar -czvf ../my_directory.tar.gz $(ls -A) && cd ..
Este funcionó para mí e incluye todos los archivos ocultos sin colocar todos los archivos en un directorio raíz llamado "." Como en la respuesta de Tomoe :
cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd -
Debería hacer el trabajo en una sola línea. Funciona bien para archivos ocultos también. "*" no expande los archivos ocultos por la expansión del nombre de la 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
find $TARGET_DIR -maxdepth 1 -type f -print0 /
| xargs --null --max-args 1 basename --zero /
| tar --create --file=result.tar --directory=$TARGET_DIR --null --files-from=-
Supone que no desea incluir ningún subdirectorio ni ningún archivo de ningún subdirectorio. Maneja con seguridad los nombres de archivo con espacios u otros caracteres inusuales. Opcionalmente, puede agregar un -name ''*.sql''
o un filtro similar al comando de búsqueda para limitar los archivos incluidos.
tar -C my_dir -zcvf my_dir.tar.gz `ls my_dir`