Comment copier des fichiers et sous-répertoires cachés (en commençant par un point) sous Linux?

10

Comment copier des fichiers cachés et des sous-répertoires cachés (ceux commençant par un point) dans le dossier A vers le dossier B? Par exemple, si j'ai cette structure:

A/a
A/b
A/.a
A/.b/
A/.b/somefile
A/.b/.c

Je voudrais copier sur B uniquement les fichiers cachés et les sous-répertoires cachés dans A:

B/.a
B/.b/
B/.b/somefile
B/.b/.c

J'ai déjà essayé cette commande: à cp A/.* Bpartir de cette autre question de superutilisateur . Cependant, il ne copie pas les sous-répertoires. A également essayé cp -r A/.* B, mais il copie .donc je termine avec une copie exacte de A (y compris les fichiers normaux). Toute aide est appréciée.

gaboroncancio
la source

Réponses:

16

Tant que vous ne recherchez que des fichiers et dossiers cachés au niveau A et que vous ne voulez pas, par exemple

A/b/.hidden

pour être copié, vous devriez pouvoir utiliser ceci:

cp -r A/.[^.]* B

Cela signifie essentiellement copier tout ce qui commence par un ., puis tout caractère autre qu'un .qui filtre .et..

Edit: Suppression de -p de la commande cp car Asker n'a pas indiqué qu'il souhaitait conserver les propriétés, les dates, etc.

Omniprésence
la source
Cela fonctionne pour les exemples de noms de fichiers et de répertoires donnés dans la question, mais le texte de la question dit «fichiers cachés et sous-répertoires cachés (ceux commençant par un point)», et cette réponse ne trouvera pas les fichiers et répertoires dont les noms commencent par deux points; par exemple ..c.
Scott
C'est un cas assez complexe, mais une préoccupation légitime néanmoins. Je n'y avais pas pensé. Vous pourriez en tenir compte en passant à .*[^.]mais vous perdriez alors les fichiers qui se terminent par un .. Je pense que vous auriez en effet besoin d'un regroupement étendu pour vraiment tenir compte de tous les cas.
Omniprésence
4

Le problème A/.*est qu'il y a le répertoire .dans Alequel correspond également le modèle.

Vous pouvez activer les modèles glob étendus et utiliser les éléments suivants:

shopt -s extglob
cp -r A/.!(?(.)) B    

Il correspond aux fichiers dont le nom commence par un point et dont le deuxième caractère n'est ni un point ni rien (? (.) Ne correspond à rien ou à un point,! (...) le nie, c'est-à-dire! (? (.)) Correspond à tout le reste que rien ou un point).

choroba
la source
+1 pour une réponse correcte. Notez que .!(@(|.))(AFAICT) équivaut à ce qui précède, (IMNSHO) un peu plus clair et un seul caractère de plus.
Scott
3

Pour des cas comme celui-ci, nous recommandons d'utiliser findau lieu de cpcomme ceci:

find A/ -type f -maxdepth 1 -name '.*' -exec cp -p {} B/ \;

La syntaxe de base se décompose comme ceci:

  • find A/ -type f: findéléments du répertoire A/dont le type est un fichier (au lieu d'un répertoire)…
  • -maxdepth 1 -name '.*': Pour cela pour un maxdepthdes 1 répertoires et dont namecommence par ..
  • -exec cp -p {} B/ \;: Et une fois ces fichiers trouvés, execla cpcommande avec un -pdrapeau pour conserver les dates / heures de la source ( {}) à la destination de B/.

J'aime utiliser maxdepthpour ajouter une couche de contrôle, donc je ne copie pas accidentellement un système de fichiers entier. Mais n'hésitez pas à supprimer cela.

JakeGould
la source
0
 for item in `find A -type d | grep -E "\."` ; do cp -r $item B ; done
  • find A -type d fournit une liste récursive dans A avec seulement des répertoires
  • grep -E "\." filtre les répertoires avec un point (ie: répertoires cachés)
  • l'option -E était nécessaire ici car sans elle cela signifie aussi "répertoire courant"
  • la barre oblique inverse est d'éviter la signification, sous l'expression régulière, de "n'importe quel caractère"
  • cp -r copier récursivement

J'ai créé la structure des fichiers et des dossiers pour A et exécuté la commande dans Git Bash (je ne suis pas avec Linux pour le moment) et cela a fonctionné.

malarres
la source
Cela se brise si les fichiers ont des espaces ou des caractères spéciaux dans leur nom ou leur chemin.
slhck
Merci d'avoir remarqué :) En fait, je me suis limité au "test case" de @gaboroncancio. Si vous pouvez me donner une autre batterie de test, je peux essayer de l'améliorer (bien sûr si vous le souhaitez, améliorez-la vous-même en modifiant cette réponse ou en créant une nouvelle réponse)
malarres
Vous pouvez simplement placer les fichiers dot dans un dossier appelé A B, puis il agirait de manière inattendue car il se développerait cp -r A B/.dotfile B. Le conseil général est de ne pas analyser findou lsproduire du tout. Si vous utilisez, findvous devez également utiliser ses propres options pour filtrer plutôt que grep, et si vous dirigez la findsortie ailleurs, utilisez -print0ou appelez directement la commande souhaitée. Voir le find manuel .
slhck
Encore plus généralement, lorsque vous travaillez avec des fichiers, il est plus sûr d'utiliser des globes shell comme expliqué dans d'autres réponses (bien qu'ils nécessitent souvent extglobd'être définis).
slhck
Merci pour le lien. Laissons alors l' findanalyse.
malarres
0

Comme alternative, vous pouvez utiliser cette autre commande si le deuxième caractère est alphanumérique ( source ):

cp -r A/.[a-zA-Z0-9]* B
gaboroncancio
la source
Cela fonctionne pour les exemples de noms de fichiers et de répertoires donnés dans la question, mais le texte de la question dit «fichiers cachés et sous-répertoires cachés (ceux commençant par un point)», et cette réponse ne trouvera pas les fichiers et répertoires dont les noms commencent par un point et un caractère spécial; par exemple, .@fooou ..c.
Scott
C'est pourquoi je souligne que cela fonctionne si le deuxième caractère est alphanumérique. ;)
gaboroncancio