Fiquei surpreso recentemente quando fiz algo parecido
mv ./* ../somedirectory
e descobri que arquivos como .gitignore
não foram movidos.
Eu faço a maior parte do meu trabalho no zsh no OS X, e essa surpresa me deixou confusa no CentOS. Eu tentei bash no OS X e encontrei o mesmo comportamento: *
não corresponde aos arquivos de ponto. Isso me parece muito indesejável, mas aparentemente é o padrão do bash. (Pode ser o padrão zsh também para tudo o que me lembro, mas posso tê-lo mudado anos atrás no meu .zshrc e esquecido que ele funcionou de maneira diferente.)
Como posso configurar o bash para se comportar conforme o esperado: para * corresponder a todos os arquivos e não ignorar os arquivos de ponto.
Caso isso não esteja claro, veja como reproduzi-lo
cd /tmp
mkdir {t,d}est
touch test/{.,}{1,2,3,4,5,6,7}
ls -hal test
mv test/* dest
ls -hal test # notice dot files are still there
ls -hal dest # notice only some files were mv'ed
Respostas:
Bater
Como você já percebeu, o bash não corresponde a um
.
no início do nome ou a uma barra. Para alterar a correspondência referente ao ponto, você deve definir adotglob
opção - man bash :Para habilitá-lo / configurá-lo com o uso do bash
shopt
, por exemplo:Para o zsh, você também pode usar a
dotglob
opção, mas precisarásetopt
habilitá-la, por exemplo:fonte
zsh
, a melhor opção é ativar o dotglob em uma base por glob:mv test/*(D) /dest
Eu testei isso e resolve o problema:
Resultado:
fonte
*
é uma glob que é expandida pela casca. Por padrão, os shells não incluem arquivos cujo nome começa com um.
(chamado arquivos ocultos ou arquivos de ponto), a menos que o líder.
seja inserido literalmente.*
ou[.]*
ou?*
ou*.*
oudir/*
não incluirá arquivos de ponto..*
oudir/.*
vontade.Então você poderia fazer:
no entanto, alguns shells, incluindo
bash
(mas nãozsh
,mksh
nemfish
) têm essa característica incorreta de que a expansão de.*
inclui as entradas de diretório especiais.
e..
que você não deseja aqui (e geralmente nunca deseja que uma glob inclua, e é por isso que eu a chamo de característica incorreta).Por esse motivo, você verá que às vezes as pessoas usam (em conchas tipo Bourne):
São três globs, o primeiro correspondendo a arquivos não ocultos, o segundo nome de arquivo começando com
.
seguido por um caractere diferente de.
e o terceiro nome de arquivo começando com..
seguido por pelo menos um caractere.No entanto, algumas conchas modernas têm maneiras melhores de contornar isso
zsh
Com
zsh
, você pode usar o(D)
qualificador glob para especificar que o glob deve incluir arquivos de ponto:zsh
também corrigiu essa outra falha no shell Bourne, pois se o padrão não corresponder, omv
comando não será executado.Como dito acima, também nunca incluirá
.
nem..
em seus globs, entãoestará seguro. No entanto, se não houver nenhum arquivo correspondente
*
ou nenhum arquivo correspondente.*
ao comando será abortado, seria melhor usar:Como em alguns outros shells, você também pode forçar todos os globs a incluir arquivos de ponto (por exemplo, se você deseja que os arquivos de ponto sejam incluídos com mais frequência do que não) com:
ou:
Depois disso, se você quiser que um determinado globo não inclua arquivos de ponto, você pode escrevê-lo:
Ou:
Bater
Infelizmente
bash
não tem qualificadores glob. Portanto, você fica com a ativação da inclusão do dotfile globalmente. Embash
, a sintaxe é:(e use
[^.]*
para globs sem arquivos ocultos).Com
dotglob
,bash
não inclui.
nem..
em globs como*
, mas ainda faz para globs como.*
.Se você definir a
GLOBIGNORE
variável como algo não vazio, ela ativará automaticamente adotglob
opção e excluirá.
e..
de.*
globs, mas não dedir/.*
ou.*/file
ones (!), Para que a proteção seja bastante inútil. Você poderia fazer,GLOBIGNORE='*/.:*/..:./*:../*:*/./*:*/../*'
mas então isso quebraria globs como*/.
ou./*
ou../*
.Uma solução melhor é usar
[.]*
oudir/[.]*
ou[.]*/file
(comdotglob
ativado) expandir arquivos de ponto, exceto.
e..
.peixe
fish
globs não incluem.
nem..
. Quando não há correspondência, dependendo da versão, funcionará comozsh
(oubash -o failglob
) oubash -o nullglob
.Funcionaria se houver arquivos ocultos e não ocultos. Caso contrário, o YMMV e com algumas versões poderá ser chamado
mv -- /dest
se não houver nenhum arquivo.ksh93
Nenhum qualificador glob
ksh93
também. Você pode incluir arquivos de ponto nos globs com:Contrariamente à
bash
s'GLOBIGNORE
, isso é feito corretamente e também corrige o problema de.*
incluindo.
e..
.yash
yash
tem umadot-glob
opção (set -o dot-glob
), mas, ao contráriobash
, as expansões glob (inclusive de*
) incluem.
e,..
portanto, são bastante inúteis.tcsh
Obras como em
bash
, que é*
incluir arquivos dot exceto.
e..
mas.*
ainda inclui.
e..
(e você pode usar[.]*
para expandir os arquivos ocultos, exceto.
e..
).fonte
A maneira mais fácil no bash de imprimir arquivos de ponto correspondentes, ignorando
.
e..
é:Testar:
Ele imprimiu todos os arquivos com pontos ou não, com a exceção notável de
.
e..
.Seu exemplo também funcionará corretamente:
Vazio de arquivos importantes.
Os arquivos do sistema
.
..
ainda existem, mas uma expansão do shell (usando *) não os inclui.E o diretório de destino contém todos os arquivos:
Por quê?
Isso funciona porque a configuração de GLOBIGNORE tem os seguintes efeitos colaterais:
shopt -s dotglob
) como arquivos de pontos matemáticos em expansões..
e..
são ignorados quando GLOBIGNORE está definido e não nulo.Detalhes no manual:
LESS=+'/The GLOBIGNORE' man bash
.Além disso, precisamos definir a variável GLOBIGNORE para conter um nome que nenhum nome de arquivo possa corresponder:
uma barra (e outra coisa apenas como uma precaução dupla).
Também pode ser útil definir o nullglob se for necessário evitar um
*
quando não houver arquivo para corresponder ao*
.fonte
Muito interessado nesta configuração de GLOBIGNORE = / + / @ user79743
Da minha experiência desactivação dotglob é mau negócio para quase todos os seus comandos (cp, mv etc.), mas o mesmo é verdade a criação do nullglob (especialmente com expressões regulares que precisa então escapando!).
No entanto, se você precisar defini-los no início do seu programa, mas interferir em partes específicas nas quais você chama comandos como cp, mv etc. ou usa expressões regulares, faça o seguinte:
fonte