Copie récursive de fichiers cachés - Linux

19

Existe-t-il un moyen simple de copier récursivement tous les fichiers cachés d'un répertoire dans un autre répertoire? Je voudrais sauvegarder uniquement tous les fichiers de paramètres dans un répertoire personnel, pas les fichiers normaux. J'ai essayé:

cp -R .* directory

mais il reconnaît .et ..copie également récursivement tous les fichiers non masqués. Existe-t-il un moyen pour que cp ignore .et ..?

Zifre
la source
Y a-t-il une différence entre -ret -R?
Chaminda Bandara

Réponses:

15

Mon préféré pour déplacer les répertoires en général a été:

tar cvf - . | (cd /dest/dir; tar xvf -)

qui tarit le répertoire courant vers stdout puis le redirige vers un sous-shell qui commence par les cd vers le répertoire de destination avant de décompresser stdin. Simple, direct, extensible - considérez ce qui se passe lorsque vous remplacez le () par un ssh sur une autre machine. Ou pour répondre à votre question, vous pourriez faire:

tar cvf - .* --exclude=\. --exclude=\.\. | (cd /dest/dir; tar xvf -)
pjz
la source
1
Merci, l'option d'exclusion est ce dont j'avais besoin. Je l'ai déjà fait dans l'autre sens, mais je garderai cela pour référence future. Cela semble vraiment flexible (bien que peut-être plus lent).
Zifre
1
Bon conseil. J'ai quelques améliorations: 1) Utilisation cd /dest/dir && tar xvf -. Le &&vous empêchera d'explorer le répertoire source si vous avez une faute de frappe dans la destination. 2) Vous n'avez besoin que de l' vindicateur tar sur l'une des commandes tar (ou aucune).
Tom Shaw
C'est suffisant. J'ai également été connu pour regrouper les choses dans l'autre sens: pour copier un srcdir à distance ici, faites(cd /src/dir && tar cf - .) | tar xvf -
pjz
17

Presque chaque fois que cela peut être résolu simplement avec:

cp -R .[a-zA-Z0-9]* directory

Il est assez inhabituel d'avoir un fichier caché qui ne commence pas par l'un de ces caractères.

D'autres correspondances de motifs sont disponibles ( .??*, .[^.]*) - voir les commentaires

Alnitak
la source
Cela ne fera qu'ignorer.-Xyz - le contenu de [] ne correspond qu'au premier caractère après le point.
Hamish Downer
6
. [^.] * attraperait tout
falstro
1
... sauf des trucs commençant par deux périodes.
falstro
@roe - c'est aussi une belle version
Alnitak
@mish - oui, je l'ai dit dans la réponse.
Alnitak
11

Vous pourriez utiliser rsync.

rsync -a ./ /some/other/directory/

qui copiera le contenu du répertoire courant (y compris les fichiers dot, mais pas inclus ..)

Rory
la source
Simple et fonctionne également pour les fichiers cachés dans des dossiers cachés.
user59183
pour moi, c'est la moins déroutante et la plus efficace des solutions proposées
palerdot
Belle solution. J'en avais également besoin pour ne pas copier entre les .gitrépertoires. L'ajout de -C fait cela et ainsi la commande devient:rsync -aC ./ /some/other/directory/
theruss
10

Je vous en supplie, éloignez-vous de l'expansion du shell sur la cpligne de commande - l'expansion du shell a toutes sortes de cas d'angle ahem "intéressants" (récursion indésirable causée par. Et .., espaces, trucs non imprimables, liens durs, liens symboliques, et ainsi de suite.) Utilisez à la findplace (il vient dans le findutilspaquet, au cas où vous ne l'auriez pas installé - ce qui serait bizarre, toutes les distributions l'installent par défaut):

find -H /path/to/toplevel/dir/ -maxdepth 1 -name '.*' -a \( -type d -o -type f -o -type l \) -exec cp -a '{}' /path/to/destination/dir/ \;

Explication étape par étape:

  • -Hentraînera de findne pas suivre les liens symboliques (sauf si le nom du répertoire de haut niveau réel que vous lui avez donné est un lien symbolique; qu'il suivra.)
  • /path/to/toplevel/dir/ est, bien entendu, censé être remplacé par vous avec le chemin du répertoire qui héberge les fichiers de paramètres et les répertoires que vous souhaitez sauvegarder.
  • -maxdepth 1empêchera findde descendre récursivement dans les répertoires dont le nom commence par un point. Nous n'en avons pas besoin pour récuser, cpnous le ferons, nous avons juste besoin des noms à ce niveau.
  • -name '.*'indique findque nous voulons que tous les noms commençant par un point. Cela ne fonctionnera pas correctement si la variable d'environnement POSIXLY_CORRECTest définie, mais elle l'est rarement (voire jamais). Il s'agit de la première condition de correspondance que nous avons spécifiée jusqu'à présent.
  • a \( ....... \)est un et suivi d'une condition plus complexe entre parenthèses (j'ai utilisé ..... pour le remplacer, c'est expliqué ci-dessous.) Nous devons échapper les parenthèses car sinon elles seront (mal) interprétées par le shell, d'où la barre oblique inverse devant eux,
  • -type d -o -type f -o -type lsont trois conditions avec un ou entre eux. -type dcorrespond aux répertoires, -type fcorrespond aux fichiers normaux et -type lcorrespond aux liens symboliques. Vous pouvez sélectionner ce que vous voulez - par exemple, si vous ne voulez pas sauvegarder les répertoires de paramètres, omettez -type d(et le -odroit derrière, évidemment.)
  • -exec ..... \;indique findd'exécuter une commande chaque fois qu'une correspondance est rencontrée. La fin de la commande est marquée par un point-virgule, auquel nous devons à nouveau échapper avec une barre oblique inverse pour éviter l'interprétation du shell. Dans cette ligne de commande, vous devez utiliser {}où vous voulez que le nom de la correspondance actuellement rencontrée se termine. Étant donné que les coquilles peuvent également mal interpréter les accolades, vous devez les placer dans des apostrophes, comme dans '{}'. La commande que nous voulons exécuter dans ce cas est cp -a '{}' /path/to/destination/dir/(-a signifie archive, qui revient dans les sous-répertoires, copie les liens symboliques sous forme de liens, et conserve les autorisations et les attributs étendus, et /path/to/destination/dir/est évidemment le nom du répertoire de destination - remplacez-le.)

Donc, en langage simple, cette findligne de commande dit ceci:

Commencez par / path / to / toplevel / dir /. Ne descendez dans aucun sous-répertoire. Trouvez tous les répertoires, fichiers et liens symboliques dont le nom commence par un point. Pour chacun de ceux que vous avez trouvés, copiez-le dans / chemin / vers / destination / dir / en préservant la nature, les autorisations et les attributs étendus.

Mihai Limbăşan
la source
1
trouver est la chose la plus utile qui soit.
M. Shiny et New 安 宇
1
Bonne réponse. Bien que je préfère -exec ... ';' Éviter la barre oblique inverse signifie que cette commande fonctionnera à la fois dans la CLI et dans la crontab :))
kubanczyk
8

J'ai toujours utilisé. ?? * pour trouver des fichiers cachés sans obtenir "." et "..". Il pourrait manquer ".a" ou quelque chose, mais je n'en ai jamais.

Paul Tomblin
la source
certainement agréable et soigné :) +1
falstro
Je ne veux pas qu'il échoue mystérieusement s'il y a des ".a"
Zifre
Je l'aime parce que si vous savez que vous n'avez pas de fichiers cachés à un seul caractère, c'est très rapide à taper.
Paul Tomblin
Ce doit être la meilleure réponse. Il devrait être voté en haut.
Ibn Saeed