Respostas:
Isenção de responsabilidade: Esta resposta lida especificamente com o Bash, mas muito disso se aplica à pergunta sobre padrões glob!
O caractere estrela ( *
) é um curinga. Há um certo conjunto de caracteres que ele substituirá e o primeiro caractere sendo um ponto ( .
) não é um deles. Este é um caso especial apenas por causa do funcionamento dos sistemas de arquivos Unix, os arquivos que começam com um ponto são considerados "ocultos". Isso significa que ferramentas como cp
, ls
etc. não as "verão", a menos que seja explicitamente instruído a fazê-lo.
Primeiro, vamos criar alguns dados de amostra.
$ mkdir .dotdir{1,2} regdir{1,2}
$ touch .dotfile{1,2} regfile{1..3}
Então agora temos o seguinte:
$ tree -a
.
|-- .dotdir1
|-- .dotdir2
|-- .dotfile1
|-- .dotfile2
|-- regdir1
|-- regdir2
|-- regfile1
|-- regfile2
`-- regfile3
Agora vamos jogar alguns jogos. Você pode usar o comando echo
para listar o que seria um caractere curinga ( *
) específico para um determinado comando, como:
$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3
$ echo reg*
regdir1 regdir2 regfile1 regfile2 regfile3
$ echo .*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2
$ echo .* *
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3
$ echo .dotdir*
.dotdir1 .dotdir2
Você pode usar o comando shopt -s dotglob
para alterar o comportamento do *
arquivo para que, além de arquivos como regfile1
ele, também corresponda .dotfile1
.
trecho da bash
página de manual
dotglob If set, bash includes filenames beginning with a `.' in the results
of pathname expansion.
Exemplo:
$ shopt -s dotglob
$ echo *
.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3
Você pode reverter esse comportamento com este comando:
$ shopt -u dotglob
$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3
Para você, você está dizendo cp
que deseja copiar todos os arquivos que correspondem ao padrão *
e que não existem arquivos.
$ cp foo/.* .
Ou você pode fazer isso se quiser tudo na foo
pasta:
$ cp foo .
Ou você pode ser explícito:
$ cp foot/.* foo/* .
Uma forma mais compacta usando expansão de chaves em bash
:
$ cp foo/{.,}* .
A qualquer momento, você pode usar o echo
truque para ver quais padrões de arquivo propostos (esse é o termo mais sofisticado para o qual a estrela faz parte).
$ echo {.,}*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 abc regdir1 regdir2 regfile1 regfile2 regfile3
Aliás, se você deseja copiar um diretório de arquivos + outros diretórios, normalmente deseja fazer isso recursivamente, essa é a -R
opção para cp
:
$ cp -R foo/. .
shopt -s dotglob
, echo *
e fornece:.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3
cp -r foo .
normalmente não funcionará, pois cp
se recusará a copiar foo
sobre si mesmo, você provavelmente quis dizer cp -R foo/. .
. (note que cp -R
é o padrão).
zsh
não inclui .
e ..
na expansão de .*
. Além disso zsh
, se um padrão não corresponder, o comando será abortado (novamente com bastante sensibilidade); portanto, no caso geral, cp foo/{,.}* .
falhará se não houver arquivos ocultos ou não ocultos.
shopt
não existe.
Com zsh
, a maneira típica é usar o D
qualificador glob (para incluir [D] ot arquivos):
cp foo/*(D) .
Observe que, com ou sem D
, os zsh globs nunca incluem .
nem ..
(como seria de esperar).
Se o que você deseja fazer é copiar todos os arquivos e diretórios de um lugar para outro, você pode usar o rsync
comando padrão . No exemplo que você fornece acima:
mkdir foo && touch foo/.test
rsync -a foo/ .
copiará recursivamente todo o conteúdo de foo
, incluindo arquivos ocultos e diretórios ocultos, no diretório atual. A barra final no final de foo/
é importante para o rsync; com ele apenas o conteúdo de foo
é copiado, sem ele o rsync também copia foo
. Por exemplo:-
mkdir src && mkdir dest && touch src/.test
rsync -a src dest // copies 'src' contents to 'dest/src'
rsync -a src/ dest // copies 'src' contents to 'dest'
Existem muitas outras opções disponíveis para ajustar o rsync, incluindo a cópia entre máquinas.
dotglob
é traduzido paraglobdots
pelo zsh que é nome de opção inválida para o bash .