Como copio um arquivo chamado começando com um ponto?

26

Estou tentando copiar todos os arquivos do diretório A para o diretório B. Todos os arquivos do diretório A estão começando com ponto, por exemplo:

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

que encontrei se usar:, cp A/* Bsempre receba erro:

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

Parece que não há nenhuma opção para cpcomo lspara lidar com entradas iniciados com ponto, alguém tem idéia de como consertar isso?

user59285
fonte

Respostas:

34

O motivo é que bash, em , *não inclui arquivos começando com ponto ( .).

Você pode correr

cp A/.* B

Ele irá avisá-lo que não copiar .ou .., ou qualquer subdiretório, mas isso é bom.

Ou, se você deseja copiar arquivos de ponto e arquivos normais juntos, execute

cp A/.* A/* B

Você também pode executar

shopt -s dotglob
cp A/* B

que funcionará bash, mas não sh.

E se você não se importa de subdiretórios serem copiados também, isso é o mais fácil:

cp -R A/ B

Dica: se algum curinga não estiver fazendo o que você espera, tente executá-lo com eco, por exemplo

$ 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
fonte
Isso é apenas um problema se você usar -r. Sem -r, ele apenas pulará os diretórios.
21914 Mikel
E o exemplo que eu dou usando também -Rdeve funcionar bem. Se você acha que está errado, explique o motivo.
Mikel
7

Se bash, você pode definir dotglobantes de copiar

shopt -s dotglob
cp A/* /destination

Ou uma linguagem de programação

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

Se você não deseja configurar o dotglob, apenas

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

fonte
O uso do dotglob OP também copiará todos os arquivos não ocultos, o que não é o que ele deseja.
#
@peoro, você deve ler a pergunta novamente. Todos os arquivos Aestão ocultos. Ele só quer copiar isso.
7

O que você está procurando é mais na linha de:

cp A/.??* B/

Isso corresponderá a todos os arquivos de ponto, mas não a "." ou "..". A maioria das soluções acima são boas, desde que você não esteja trabalhando recursivamente. Mas assim que você quiser fazer algo como:

cp -R A/.??* B/

Sem omitir "..", você copiará tudo do diretório-pai para baixo, incluindo arquivos não-dotfiles.

John Westlund
fonte
1
Isso perderá arquivos de ponto com um único caractere, como .aou .x. O menor padrão de globbing que encontrei que corresponde a todos os arquivos de pontos, exceto .e ..é .[^.]*.
pavon
2

Eu justed tentei o seguinte e funciona apenas encontrar ...

cp A/.* B/
Andrew White
fonte
2
Isso também passará A/.e A/..como parâmetros para cp, o que pode ser problemático caso o OP também precise copiar diretórios (usando cp -r)
peoro
2

Isso não cpé culpa , é o bash: o bash se expande *em todos os .arquivos não ocultos (ou seja: não começando com ).

O Bash se expandirá .*(portanto A/.*, no seu caso) com todos os arquivos que começam com ., mas infelizmente também inclui .e ..(diretórios atual e pai) que você provavelmente desejará ignorar. (Observe que outros shells, como o zsh, não os incluiriam, e o IIRC também bash, depois de definir algumas opções).

Uma solução fácil poderia ser remover .e ..dos arquivos encontrados .*, de uma maneira (muito) hacky como esta:

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

ou este (provavelmente mais limpo: ele usa findpara encontrar os arquivos para copiar):

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

mas você provavelmente encontrará soluções mais limpas.

peoro
fonte
por que você deve usar um for loope depois criar um grepprocesso extra apenas para fazer um trabalho como esse cp A/.*? cpirá ignorar o "." e diretórios "..".
1

Se todos começarem com um ponto, basta usar 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

Espero que isto ajude!

Xavier Holt
fonte
1

Você pode usar este script

IFS = $ '\ n'; para agir em $ (encontre A -d 1); faça cp -R "$ act" B; feito

teki
fonte
0

cópia de:

cp A/.* B

Lista:

ls -l A/.*

listar arquivos sem diretórios descendentes:

ls -ld A/.*
Blessed Geek
fonte
0

Você deve excluir. e .. da lista de arquivos passada para o cp!

Isso é seguro:

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

Este é um tópico antigo ... mas sempre consegui copiar todos os arquivos. Incluindo arquivos / pastas que começam com '.'

O exemplo copiará todos os arquivos e pastas:

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

Ontologik
fonte