Comment copier un fichier nommé commençant par un point?

26

J'essaie de copier tous les fichiers du répertoire A dans le répertoire B. Tous les fichiers du répertoire A commencent par un point, par exemple:

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

que j'ai trouvé si j'utilise cp A/* B:, obtenez toujours une erreur:

cp: cannot stat 'A/*': no such file or directory

Il semble qu'il n'y a pas d' option pour cpque lspour les entrées poignée ouvertes avec un point, quelqu'un a idée de comment résoudre ce problème?

user59285
la source

Réponses:

34

La raison en est que dans bash, *n'inclut pas les fichiers commençant par dot ( .).

Tu peux courir

cp A/.* B

Il vous avertira qu'il n'a pas copié .ou .., ni aucun sous-répertoire, mais c'est très bien.

Ou, si vous souhaitez copier des fichiers dot et des fichiers normaux ensemble, exécutez

cp A/.* A/* B

Vous pouvez également exécuter

shopt -s dotglob
cp A/* B

qui fonctionnera bash, mais pas sh.

Et si cela ne vous dérange pas de copier des sous-répertoires, c'est le plus simple:

cp -R A/ B

Astuce: si jamais des caractères génériques ne font pas ce que vous attendez, essayez de l'exécuter avec écho, par exemple

$ echo A/*
A/file1 A/file2

$ echo A/.*
A/. A/.. A/.hidden1 A/.hidden2

$ echo A/.* A/*
A/. A/.. A/.hidden1 A/.hidden2 A/file1 A/file2

$ shopt -s dotglob
$ echo A/*
A/file1 A/file2 A/.hidden1 A/.hidden2
Mikel
la source
C'est seulement un problème si vous utilisez -r. Sans -r, il sautera simplement les répertoires.
Mikel
Et l'exemple que je donne en utilisant -Rdevrait très bien fonctionner aussi. Si vous pensez que c'est faux, veuillez expliquer pourquoi.
Mikel
7

Si bash, vous pouvez définir dotglobavant de copier

shopt -s dotglob
cp A/* /destination

Ou un langage de programmation

$ ruby -rfileutils -e  'Dir[".*"].each {|x| FileUtils.copy(x,"/destination") if File.file?x}'

Si vous ne souhaitez pas définir dotglob,

cp A/.* /destination 2>/dev/null

la source
L'utilisation de dotglob OP copiera également tous les fichiers non cachés, ce qui n'est pas ce qu'il veut.
peoro
@peoro, vous devriez relire la question. Tous les fichiers Asont masqués. Il veut juste copier ça.
7

Ce que vous cherchez, c'est plutôt:

cp A/.??* B/

Cela correspondra à tous les fichiers dot, mais pas "." ou "..". La plupart des solutions ci-dessus sont correctes tant que vous ne travaillez pas récursivement. Mais dès que vous voulez faire quelque chose comme:

cp -R A/.??* B/

Sans omettre "..", vous copiez tout du répertoire parent vers le bas, y compris les fichiers non dot.

John Westlund
la source
1
Cela manquera les fichiers de points qui sont un seul caractère, comme .aou .x. Le modèle de globbing le plus court que j'ai trouvé qui correspond à tous les fichiers de points sauf .et ..est .[^.]*.
pavon du
2

J'ai juste essayé ce qui suit et ça marche, trouvez ...

cp A/.* B/
Andrew White
la source
2
Cela passera également A/.et en A/..tant que paramètres à cp, ce qui pourrait être problématique dans le cas où OP doit également copier des répertoires (en utilisant cp -r)
peoro
2

Ce n'est pas cpla faute , c'est bash: bash se développe *dans tous les .fichiers non cachés (c'est-à-dire: ne commençant pas par ).

Bash se développera .*(ainsi A/.*, dans votre cas) avec tous les fichiers commençant par ., mais malheureusement, il inclut également .et ..(répertoires actuel et parent) que vous voudrez probablement ignorer. (Notez que d'autres shells, comme zsh, ne les incluraient pas, et IIRC bash aussi, après avoir défini certaines options).

Une solution simple pourrait être de supprimer .et ..de supprimer les fichiers correspondants .*, d'une manière (très) hacky comme celle-ci:

cp $( for F in A/.*; do echo $F | grep -v "^\.*$"; done ) B

ou celui-ci (probablement plus propre: il utilise findpour trouver les fichiers à copier):

cp $( find A -maxdepth 1 -mindepth 1 -name ".*" ) B

mais vous trouverez probablement des solutions plus propres.

peoro
la source
pourquoi devriez-vous utiliser un for looppuis créer un grepprocessus supplémentaire juste pour faire un travail comme cp A/.*? cpignorera le "." et les répertoires "..".
1

S'ils commencent tous par un point, utilisez simplement A/.*:

[holt@Michaela test]$ cp A/* B
cp: cannot stat `A/*': No such file or directory

[holt@Michaela test]$ cp A/.* B
cp: omitting directory `A/.'
cp: omitting directory `A/..'
[holt@Michaela test]$ ls -al B
total 8
drwxrwxr-x. 2 holt holt 4096 2011-03-31 16:57 .
drwxrwxr-x. 4 holt holt 4096 2011-03-31 16:57 ..
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .a
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .b
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .c

J'espère que cela t'aides!

Xavier Holt
la source
1

Vous pouvez utiliser ce script

IFS = $ '\ n'; pour agir dans $ (trouver A -d 1); faire cp -R "$ act" B; terminé

teki
la source
0

copie:

cp A/.* B

liste:

ls -l A/.*

liste des fichiers sans répertoires décroissants:

ls -ld A/.*
Geek béni
la source
0

Vous devez exclure. et .. de la liste des fichiers passés à cp!

C'est sûr:

ls -1d A/.[a-zA-Z]* | xargs -i cp -rp {} B
AmitP
la source
0

C'est un vieux fil de discussion ... mais j'ai toujours pu copier tous les fichiers. Y compris les fichiers / dossiers commençant par "."

L'exemple copiera tous les fichiers et dossiers:

cp -aup /root/.* / backup / root /

Ontologik
la source