Como copiar arquivos e subdiretórios ocultos (começando com um ponto) no linux?

10

Como copiar arquivos ocultos e subdiretórios ocultos (os que começam com um ponto) na pasta A para a pasta B? Por exemplo, se eu tenho essa estrutura:

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

Gostaria de copiar para B apenas os arquivos ocultos e subdiretórios ocultos em A:

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

Eu já tentei este comando: cp A/.* Ba partir desta outra questão superusuário . No entanto, ele não copia os subdiretórios. Também tentei cp -r A/.* B, mas ele copia, .então eu termino com uma cópia exata de A (incluindo os arquivos normais). Qualquer ajuda é apreciada.

gaboroncancio
fonte

Respostas:

16

Contanto que você esteja procurando apenas arquivos e pastas ocultos no nível A e não queira, por exemplo

A/b/.hidden

para ser copiado, você poderá usar isto:

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

Basicamente, significa copiar qualquer coisa que comece com um .caractere diferente de um .que filtra .e..

Edit: Removido -p do comando cp, já que Asker não indicou que deseja preservar quaisquer propriedades, datas etc.

Onipresença
fonte
Isso funciona para os nomes de arquivos e diretórios de exemplo fornecidos na pergunta, mas o texto da pergunta diz "arquivos ocultos e subdiretórios ocultos (os que começam com um ponto)", e esta resposta não encontrará arquivos e diretórios cujos nomes começam com dois pontos; por exemplo ..c,.
Scott
Esse é um caso bastante delicado, mas uma preocupação legítima, no entanto. Eu não tinha considerado isso. Você pode explicar isso mudando para, .*[^.]mas perderá os arquivos que terminam com a .. Eu acho que você realmente precisaria de globbing prolongado para realmente responder a todos os casos.
Onipresença
4

O problema A/.*é que existe o diretório .no Aqual também corresponde ao padrão.

Você pode ativar os padrões estendidos de glob e usar o seguinte:

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

Ele corresponde aos arquivos cujo nome começa com um ponto e cujo segundo caractere não é nem um ponto nem nada (? (.) Corresponde a nada ou um ponto,! (...) o nega, ou seja,! (? (.)) Corresponde a todo o resto do que nada ou um ponto).

choroba
fonte
+1 para uma resposta correta. Observe que .!(@(|.))(AFAICT) é equivalente ao acima, (IMNSHO) um pouco mais claro e apenas um caractere a mais.
Scott
3

Para casos como este, recomendo usar em findvez de cp:

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

A sintaxe básica se divide assim:

  • find A/ -type f: finditens no diretório A/cujo tipo é um arquivo (em vez de um diretório)…
  • -maxdepth 1 -name '.*': Para isso em um maxdepthdos diretórios 1 e cujo namecomeça com ..
  • -exec cp -p {} B/ \;: E uma vez que esses arquivos são encontrados, execo cpcomando com um -psinalizador para preservar datas / horas da origem ( {}) para o destino de B/.

Eu gosto de usar maxdepthpara adicionar uma camada de controle, para não copiar acidentalmente um sistema de arquivos inteiro. Mas fique à vontade para remover isso.

JakeGould
fonte
0
 for item in `find A -type d | grep -E "\."` ; do cp -r $item B ; done
  • find A -type d fornece uma lista recursiva dentro de A apenas com diretórios
  • grep -E "\." filtra diretórios com um ponto (ou seja: diretórios ocultos)
  • a opção -E era necessária aqui, porque sem ela significa também "diretório atual"
  • a barra invertida é evitar o significado, sob regexp, de "qualquer caractere"
  • cp -r copiar recursivamente

Eu criei a estrutura de arquivos e pastas para A e executei o comando no Git Bash (não estou com um Linux no momento) e funcionou.

malarres
fonte
Isso é interrompido se os arquivos tiverem espaços em branco ou caracteres especiais em seu nome ou caminho.
slhck 23/10
Obrigado por perceber :) Na verdade, eu me limitei ao "caso de teste" do @gaboroncancio. Se você pode me dar outra bateria de testes que podem tentar melhorar isso (claro, se quiser, melhorá-lo por si mesmo, quer editar esta resposta ou a criação de uma nova resposta)
malarres
Você poderia simplesmente colocar os arquivos de ponto em uma pasta chamada A Be, em seguida, agiria inesperadamente, porque expandiria para cp -r A B/.dotfile B. O conselho geral é não analisar findnem gerar lssaída . Se você usar find, também deverá usar suas próprias opções para filtrar e não grep, e se canalizar a findsaída para outro lugar, use -print0ou chame diretamente o comando desejado. Veja o find manual .
slhck
De maneira ainda mais geral, ao trabalhar com arquivos, é mais seguro usar os globs do shell, conforme explicado em outras respostas (embora muitas vezes precisem extglobser configurados).
slhck
Obrigado pelo link. Vamos deixar a findanálise então.
Malarres 27/10/2014
0

Como alternativa, você pode usar este outro comando se o segundo caractere for alfanumérico ( origem ):

cp -r A/.[a-zA-Z0-9]* B
gaboroncancio
fonte
Isso funciona para os nomes de arquivo e diretório de exemplo fornecidos na pergunta, mas o texto da pergunta diz "arquivos ocultos e subdiretórios ocultos (os que começam com um ponto)", e esta resposta não encontrará arquivos e diretórios cujos nomes começam com um ponto e um caractere especial; por exemplo, .@fooou ..c.
Scott
É por isso que aponto que funciona se o segundo caractere for alfanumérico. ;)
gaboroncancio