'command. *' atua no diretório pai [duplicado]

22

Alguém da nossa equipe queria alterar de forma recursiva as permissões de usuário em todos os diretórios ocultos em um diretório inicial de usuários. Para isso, ele executou o seguinte comando:

cd /home/username
chown -R username:groupname .*

Ficamos muito surpresos quando percebemos que ele de fato alterou recursivamente as permissões de todos os diretórios de usuários em / home, porque .* é igual a .. também. Você teria esperado esse comportamento no Linux?

    
por g000ze 26.03.2015 / 14:54

7 respostas

17

Eu sempre me queimo quando tento usar. * para qualquer coisa e há muito tempo mudou para o uso de classes de caracteres:

chown -R username.groupname .[A-Za-z]*

é como eu teria feito isso.

Edit: alguém apontou que isso não acontece, por exemplo, arquivos de pontos como ._Library . A captura de todas as classes de caracteres a serem usadas seria

chown -R username.groupname .[A-Za-z0-9_-]*
    
por 26.03.2015 / 15:00
10

Usando o globbing estendido ( shopt -s extglob ), você pode usar

.!(.|)

i.e. ponto não seguido por ponto ou nada.

    
por 26.03.2015 / 15:20
10

O caractere . só é excluído da correspondência de curinga quando é o primeiro caractere do nome do arquivo e seria correspondido por um curinga. No padrão .* , o * corresponde cadeias começando com . , portanto .* inclui .. (bem como . , com * correspondendo à cadeia vazia). Esta é uma consequência direta das regras de correspondência de padrões, por mais irritantes que possam ser.

Faz sentido abrir uma exceção e excluir sistematicamente . e .. das correspondências, mas não foi assim que foi feito historicamente, portanto, muitos shells Bourne / POSIX ( sh , dash , bash , AT & T ksh , yash …) inclui-os, assim como (t) csh e até mesmo peixe 1.x. Alguns shells excluem . e .. de todas as correspondências com curingas: zsh, pdksh / posh / mksh (diferente de AT & T ksh), fish ≥2.0 .

Se você definir GLOBIGNORE para qualquer valor não vazio, bash alternará para o comportamento conveniente, mas não padrão, de excluir . e .. das correspondências. A configuração GLOBIGNORE também desativa o comportamento de excluir arquivos de ponto; com GLOBIGNORE='.*' , você obtém o comportamento normal de ./* , excluindo os arquivos de pontos, mas ./.* corresponde apenas aos arquivos de ponto e não . ou .. . Defina GLOBIGNORE=.:.. (ou GLOBIGNORE=. ) para que ./* correspondam a todos os arquivos, incluindo arquivos de ponto, mas excluindo . e .. .

Em ksh93, defina FIGNORE='@(.|..)' para excluir . e .. das correspondências, mas inclua arquivos de ponto. Assim, .* expandirá para arquivos de pontos, mas não incluirá . ou .. .

Sem recorrer a funcionalidades específicas da shell, pode combinar ficheiros dot com as duas globs seguintes:

.[!.]* ..?*

e todos os arquivos (excluindo . e .. ) com os seguintes três globs:

..?* .[!.]* *

Mas você precisa tomar cuidado porque um ou vários globs podem não corresponder a nenhum arquivo, o que faria com que o padrão correspondente permanecesse não expandido.

Para evitar surpresas, pode ser mais fácil usar find . find nunca recorre ao diretório pai (a menos que seja instruído a seguir links simbólicos).

find /home/username/. -name . -o -prune -name '.*' -exec chown -R username:groupname {} +
    
por 27.03.2015 / 01:24
6

Se o próprio diretório compartilhar a mesma propriedade que seus arquivos (ocultos ou não), você poderá chown recursivamente. A opção -R incluirá arquivos ocultos ao recorrer dentro do diretório atual.

$ chown user:group . -R # Will include all hidden files
    
por 26.03.2015 / 15:29
6

Considere usar find ( -maxdepth é uma extensão não POSIX, mas deve estar prontamente disponível no Linux):

find . -maxdepth 1 -type d -name '.*' -exec chown -R user:group {} +
    
por 26.03.2015 / 15:16
1

Uma variação da solução Chris Down que filtra apenas diretórios ocultos e remove as opções -R. Seu requisito original era alterar a propriedade e classificar o grupo de diretórios ocultos, não seu conteúdo.

find /home/username -maxdepth 1 -type d -name '.*' -exec chown user:group {} +
    
por 26.03.2015 / 15:42
1

Acho que você poderia usar ls -A , especificamente:

chown -R username:groupname $(ls -A | grep '^\.')

Isso faz o que você espera que o .* faça, corresponde todos os arquivos no diretório atual que começam com . , excluindo . e .. . Mas note que isso não se comportará de forma idêntica a um bash glob se você precisar que ele corresponda a nomes de arquivos, como arquivos com espaços neles.

    
por 26.03.2015 / 20:18