creación de archivo usando tar incluyendo todos los 'archivos de puntos' pero excluyendo todos los subdirectorios y la estructura de directorios / wo


18

Quiero hacer una copia de seguridad de todos los 'archivos de puntos' (fe .zshrc) en mi directorio de inicio con tar , pero excluyendo la estructura del directorio y todos los subdirectorios.

Lo he intentado varias veces con diferentes comandos, pero lo mejor que logré fue un archivo que incluyera también los directorios ocultos $HOME.

#!/bin/zsh
BACKUPFILE=dotfile_backup.tar.gz
tar --create --file=$HOME/$BACKUPFILE --auto-compress --no-recursion --exclude=. --exclude=.. --exclude=*/ --directory=$HOME .*

También pensé en usar findy canalizar el resultado al alquitrán, pero sin suerte. ¿Alguien sabe cómo lograr esta tarea, aparentemente fácil?

PD: La mayoría de las veces cuando uso tar para crear un archivo, tengo que pensar en xkcd comic:

xkcd 1168 :)


La respuesta de sim funciona, pero si alguien tiene una expresión regular que solo coincide con los archivos ocultos, ¡publíquela!
klingt.net

1
Seguramente esto se lograría mejor con su caparazón. Entiendo que zsh tiene globos que seleccionan solo archivos, *(.)y creo que excluye .y ..de .*forma predeterminada (y de .*(.)todos modos no serían recogidos , ya que selecciona solo archivos). Yo no uso zsh, así que no estoy lo suficientemente seguro como para convertir esto en una respuesta.
evilsoup

Respuestas:


14

Puede usar este comando para hacer una copia de seguridad de todos sus dotfiles ( .<something>) en su $HOMEdirectorio:

$ cd ~
$ find . -maxdepth 1 -type f -name ".*" -exec tar zcvf dotfiles.tar.gz {} +

regex usando solo alquitrán?

Método 1

Investigué esto bastante y salí vacío. El factor limitante sería que cuando tarse realiza su exclusión, la barra inclinada final ( /) que aparece con los directorios no es parte de la ecuación cuando tar está realizando su coincidencia de patrones.

Aquí hay un ejemplo:

$ tar -v --create --file=do.tar.gz --auto-compress --no-recursion --exclude={'.','..','.*/'} .*
.qalculate/
.qt/
.qterm/
.qtoctave/
.RapidSVN
.RData
.Rhistory

Esta variante incluye una exclusión de .*/y puede ver con el interruptor detallado activado en tar -v, que estos directorios están pasando por esa exclusión.

método # 2

Pensé que tal vez los interruptores --no-wildcards-match-slasho --wildcards-match-slashrelajarían la avaricia del .*/pero esto tampoco tuvo efecto.

Eliminar la barra de la exclusión .*tampoco era una opción, ya que eso tarindicaría excluir todos los archivos de puntos y directorios de puntos:

$ tar -v --create --file=do.tar.gz --auto-compress --no-recursion --exclude={'.','..','.*'} .*
$

método # 3 (¡feo!)

Entonces, la única otra alternativa que puedo concebir es proporcionar una lista de archivos tar. Algo como esto:

$ tar -v --create --file=do.tar.gz --auto-compress --no-recursion --wildcards-match-slash --exclude={'.','..','.*/'} $(ls -aF | grep -E "^\..*[^/]$")
.RapidSVN
.RData
.Rhistory

Este enfoque tiene problemas si el número de archivos excede la cantidad máxima de espacio para pasar argumentos a un comando sería un problema evidente. El otro es que es feo y demasiado complejo.

¿Entonces Que aprendimos?

No parece haber una manera directa y elegante de lograr esto usando tarexpresiones regulares. En cuanto al comentario de @terdon, find ... | tar ...es realmente la forma más adecuada de hacer esto.


Tenía muchas ganas de lograr que se haga con el regex, pero yo debería haber sabido que no va a funcionar de esa manera :)
klingt.net

@ klingt.net - debería ser posible, estoy buscando ahora.
slm

@ klingt.net ¿por qué preferirías la forma más complicada? Al regexusarlo probablemente necesitará escapar del punto inicial y tendrá problemas para ignorar .y ... Estoy seguro de que es posible, ya que SLM probablemente lo demostrará, pero no veo por qué valdría la pena.
terdon

1
@ klingt.net: todo lo que el findcomando encuentra se pasa como argumento a tar. El {}dice dónde quiere que vayan esos resultados en el -execcomando correspondiente . El +dice a añadir tantos resultados de findcomo quepan en la línea de comandos y llamar a tarsólo un par de veces en lugar de cada vez que se encontró resultado.
slm

1
@ klingt.net: no hay forma de lograr esto usando regexy tarporque no hay forma de aislar los directorios de puntos ( .blah/). Tar no usa la barra inclinada final al hacer la exclusión.
slm

4

Este tipo de control sobre los archivos coincidentes está muy fuera de la zona de confort del alquitrán. Sus reglas para la coincidencia de archivos se limitan a coincidencias simples sobre nombres.

find es una forma, pero como tienes zsh, lo tienes más fácil:

tar -cf "$HOME/$BACKUPFILE" --auto-compress .*(.)

Eso .entre paréntesis al final de la expresión comodín es un calificador global que dice "solo coincide con los archivos normales".

Los enlaces simbólicos a los archivos normales no coinciden. Si cambia a .*(-.), se incluirán, pero el archivo no terminará en el archivo a menos que también esté incluido. Si desea reemplazar el enlace simbólico por sus objetivos, haga eso .*(-.:A):Aagrega el modificador de expansión del historial que resuelve todos los enlaces simbólicos a una ruta que no usa enlaces simbólicos.


3

Esta respuesta se basa en slm, pero también le mostraré cómo incluir directorios que comiencen con .

Para comprimir archivos de puntos en su directorio de inicio:

$ cd
$ find . -maxdepth 1 -type f -name ".?*" -exec tar czfv dotfiles.tgz {} +

Para incluir directorios:

$ find . -maxdepth 1 -name ".?*" -exec tar czfv dotfiles.tgz {} +

El ?es opcional en el primer comando, pero no en el segundo, de lo contrario, findincluirá el .directorio (actual).


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.