shopt -s extglob não está funcionando como esperado

3

Estou tentando alterar de forma recursiva as permissões de arquivo em uma instalação do WordPress que afeta tudo abaixo da pasta raiz do documento public_html, excluindo determinadas pastas.

Eu configurei extglob com shopt -s extglob

Quando executo o seguinte comando, ele não consegue excluir a pasta que eu quero excluir   ls -R -alh ./public_html/!(*uploads*) | grep uploads

A lista acima lista vários arquivos na pasta uploads - não deve listar nenhum.

Claro que o comando acima é apenas um teste; Eu usarei chmod no script atual.

Eu tentei várias combinações diferentes e todas falharam; por exemplo, o seguinte:

ls -R -alh ./public_html/!(wp-content/uploads*)

ls: cannot access ./public_html/!(wp-content/uploads*): No such file or directory

Esta é minha primeira tentativa de usar exclusões com comandos shell e posso estar cometendo um erro simples.

Alguma idéia do que estou fazendo errado?

Por favor, note: o propósito da questão é entender melhor o extglob em vez de encontrar alternativas. Eu posso escrever alternativas, mas como nunca usei extglob antes de ter dificuldade em entender a sintaxe.

    
por DeveloperChris 11.07.2016 / 03:13

2 respostas

6

Primeiro, o extglob controla o que ls vê em sua linha de comando. Não não controla o que o ls faz com o que vê na linha de comando. Isso é importante porque a opção -R para ls diz a ls para explorar recursivamente os diretórios que ele vê na linha de comando. Portanto, mesmo que os diretórios *uploads* não sejam fornecidos explicitamente na linha de comando, ls os encontrará quando explorar seus diretórios pai.

Segundo, como você sabe, não analise ls . A saída de ls não é para uso em pipelines ou scripts. Tentar usá-lo dessa maneira acaba levando à infelicidade.

Em terceiro lugar, para obter os arquivos desejados, tente:

find ./public_html ! -path '*uploads*'

Para explicar:

  • O ./public_html informa ao localizar para começar a procurar no diretório ./public_html .

  • Por si só, a opção -path '*uploads*' corresponde a qualquer caminho que contenha o padrão *uploads* . ( -path é semelhante à opção -name do find, mas path inclui os nomes dos diretórios.) O ! anterior, no entanto, indica negação. Portanto, a opção ! -path '*uploads*' exclui qualquer caminho que corresponda a *uploads* .

Para obter a saída do estilo ls enquanto ainda estiver usando os recursos de find , considere:

find ./public_html ! -path '*uploads*' -exec ls -dalh {} +
    
por 11.07.2016 / 03:38
1

O John1024 adicionou uma boa solução ao seu aparente problema, mas com base nos comentários, você gostaria de entender melhor o extglob. Eu suspeito que um dos principais mal-entendidos pode ter sido que os extglobs funcionariam de maneira recursiva - que dizer ./public_html/!(*uploads*) excluiria algo chamado ./public_html/wp-content/uploads/ . Os globs (expansão de nome de arquivo) funcionam apenas em um único nível de diretório por vez. Enterrado no manual bash, em Expansão do nome de arquivo é:

When matching a filename, the slash character must always be matched explicitly.

Assim, como John1024 disse, o comando ls não tinha nenhum parâmetro (expandido) para ele que estivesse no formato ./public_html/*uploads* , mas poderia ter um parâmetro como ./public_html/wp-content (o que não é corresponde ao padrão excluído), que foi então dito -R para listar recursivamente.

Para excluir *uploads* diretórios usando extglobs na linha de comando, você teria que criar um comando que tivesse tantas exclusões quanto subdiretórios:

ls -dalh ./public_html/!(*uploads*) \
         ./public_html/!(*uploads*)/!(*uploads*) \
         ./public_html/!(*uploads*)/!(*uploads*)/!(*uploads*)
# ... etc ...

... sendo também cuidadoso para não usar a bandeira -R de ls. O mesmo risco -R seria aplicado a um comando chmod. Um risco potencial aqui é que se qualquer subdiretório tiver arquivos "muitos", você corre o risco de preenchendo a lista de argumentos para ls . Essa abordagem é frágil, pois não captura diretórios recém-criados que são mais profundos do que o número de padrões que você gravou, e quebraria ( ls irá reclamar de um diretório ausente) se você já tiver menos subdiretórios do que o número de padrões fornecidos, que é a longa explicação de porque encontrar é o caminho certo ferramenta para este trabalho.

    
por 12.07.2016 / 17:59