Copier le contenu du répertoire à l'aide de la commande 'cp'

33

Comment copier tout le contenu d'un répertoire dans un autre?

Par exemple:

$ cd /home/newuser
$ cp -a /backup/olduser/* .

Le problème avec ce qui précède est que le modèle globant '*' correspond aux répertoires cachés '.' et '..' et vous vous retrouvez avec un répertoire 'olduser' à l'intérieur de 'newuser', ainsi que son contenu.

Vous pouvez aussi faire quelque chose comme ça:

$ rmdir /home/newuser
$ cp -a /backup/olduser /home/newuser

Mais que se passe-t-il si newuser contient déjà des fichiers et des répertoires par défaut?

Quel est le moyen le plus simple, le plus correct, le plus facile à retenir et sans faille pour déplacer le contenu d'un répertoire vers un autre à l'aide de la commande de base 'cp' et du shell?

Der Hochstapler
la source

Réponses:

31

Essayer:

cp -ra /backup/olduser/. /home/newuser
Nagul
la source
C'est génial, mais je n'arrive pas à comprendre comment cela fonctionne. Je pense que c'est probablement parce que je ne comprends pas comment .et ..travaille. Soin d'expliquer?
Bradley.ayers
Cela a fonctionné pour moi mais cp -r ./a bn'a pas. Une idée pourquoi?
Brig
3
fonctionne pour moi aussi, mais l' roption n'est pas nécessaire. L' aoption implique r.
MountainX
1
le paramètre -r semble être un peu redondant à ce stade!
Maître de la célébration
Le -aparamètre ne fait rien pour aider dans cette situation. La commande cp -r ./a/. bcopiera le contenu, et uniquement le contenu du répertoire, adans le répertoire b. Le -adrapeau préserve les liens, les horodatages, etc., ce qui n’est pas pertinent pour la question.
Steen Schütt
23

Deux répertoires a et b.

Les deux ont des fichiers dans.

Vous vous trouvez dans un répertoire contenant a et b.

cp -r ./a b

-r = récursivement.

Rich Bradshaw
la source
Vous ne voulez pas que -a récupère tous les fichiers?
bw
7
L'argument -a n'est pas compatible avec tous les fichiers, c'est un raccourci pour l'archive, il préservera la propriété du fichier, les permissions, les temps d'accès, etc. L'argument -a (bien que très utile) n'est pas une option standard, et plusieurs implémentations de cp pas le fournir.
theotherreceive
1
@mch: automatiquement inclus, car vous avez dit cpde copier un répertoire aet a/.somedotfileest contenu par a. S'il bexiste, cette commande créera une copie exacte de aat b/a.
Quack Quichotte
2
Manière simple:cp -R /some/dir/* /another/dir
n0pe
1
Ceci copie a / foo vers b / a / foo au lieu de b / foo
Sparr
19

Rappelez-vous que, par défaut, cpcopie le premier répertoire dans le deuxième répertoire si le deuxième existe.

Par exemple cp -r a bva copier le répertoire a dans b. S'il bn'existe pas, il sera créé avec le contenu de a.

Si vous souhaitez copier le contenu de adans b(par exemple, lors de la copie d'un système de fichiers complet dans un point de montage), utilisez:

cp -r a/. b

comme dans la réponse précédente.

Veuillez également noter que -a, utilisé dans certaines des autres réponses, est identique à -dr --preserve=allet préservera les horodatages, le contexte et les attributs étendus.

Nicolas Bonnefon
la source
Comment ça /.marche?
bradley.ayers
a/.représente le contenu du répertoire 'a' par opposition au répertoire lui-même, dans la plupart des cas, il est également synonyme d'utilisation cp -révite le comportement par défaut de cp (copie d'un INTO b).
Nicolas Bonnefon
C'est un truc génial, c'est exactement ce que je cherchais mais que je n'ai pas trouvé ailleurs - tout ce 'foo / *' ou '-r foo /' qui échoue dans les virages.
Ténérife
@TimoHuovinen '.' n'est pas du tout un joker. C'est littéralement le répertoire "parent", et ".." est le grand-parent. Cela signifie '/foo/./././././.' est le même répertoire que '/ foo', et '/ foo / bar / ..' est le même répertoire que '/ foo'. Considérez-les comme des liens en dur intégrés au système de fichiers.
Quuxman
@quuxman merci, je n'étais pas au courant à l'époque. Je vais retirer mon vieux commentaire pour éviter de dérouter les gens.
Timo Huovinen
6

Sauf si vous avez sérieusement reconfiguré votre shell, le motif globbing '*' ne correspond pas à '.' ou '..', comme vous pouvez le vérifier en utilisant simplement echo *. Au lieu de cela, il omet les fichiers dont le nom commence par un «.», Votre approche omettra donc tous les fichiers cachés. Vous pouvez modifier une partie de ce comportement avec les options du shell, par exemple l'option dotglob dans bash, mais ce ne sera alors pas l'option portable et robuste que vous recherchez.

Si vous avez besoin de le faire plus d'une ou deux fois, je vous recommande de vous pencher sur rsync ou à l'unisson (en fonction des besoins spécifiques) avec des spécifications source et cible soigneusement élaborées.

Une autre alternative consiste à placer le répertoire source dans une archive et à le décompresser sur le répertoire cible existant.

Peter Eisentraut
la source
1
J'utilise ceci: ( cd /src/dir ; tar cf - . ) | ( cd /dest/dir ; tar xf - )... le tar cf - .répertoire source du fichier compressé, fichiers inclus, et le crache dans STDOUT, qui est acheminé vers le STDIN du tar xf -.
Quack Quichotte
Je pense que le but principal de l'OP est de savoir comment référencer des fichiers qui commencent par '.' mais pas le spécial '.' et les répertoires '..'. Il existe une solution beaucoup plus élégante ci-dessus au lieu d'utiliser rsync ou un autre programme complexe.
Quuxman
2

Cela va copier les fichiers normaux et cachés, en excluant le répertoire parent ( ..):

cd /directory/to/copy
cp -r * .[^.]* /destination/directory

Si vous n'excluez pas le répertoire parent, vous obtenez également tout le contenu de ..votre répertoire de destination.

mch
la source
1
Mais cela exclut toujours les noms commençant par .. (par exemple, ...ou ..super-hidden).
Scott
0

Pour copier des fichiers commençant par un point, faites simplement cp. * Target /

Le plus simple est donc de faire la commande cp deux fois.

Comme le dit Peter Eisentraut, les règles de globbing normales n'incluent pas .. et. (hm, comment finir cette phrase?;)

Utilisez simplement -r pour le rendre récursif et -i pour que cp vous demande si vous voulez vraiment écraser un fichier.

cp -ri /backup/olduser/* /newuser/
cp -ri /backup/olduser/.* /newuser/
gaqzi
la source
Habituellement *ne correspond pas .ou .., mais si vous utilisez .*. Essayez echo .*. Vous pouvez exclure .et ..avec le motif suivant: .[^.]*.
MCH
@mch: Mais .[^.]*exclut toujours les noms qui commencent par .. (par exemple, ...ou ..super-hidden).
Scott
0

Cela fonctionne pour la copie de tous les fichiers et répertoires à l'exception des répertoires cachés de manière récursive du répertoire en cours vers n'importe où:

cp -rf * ^.* 
Seeeve
la source