Como usar glob estendido com parênteses em um comando passado para `bash -c`?

Como usar glob estendido com parênteses em um comando passado para `bash -c`?

Estou tentando usar um glob estendido bash -c, mas não encontrei uma maneira de fazê-lo funcionar.

Coisas que eu tentei

  1. bash -c 'for f in *.!(ext); do echo $f; done'

    Resultado:

    bash: -c: line 0: syntax error near unexpected token `('
    

     

  2. bash -c 'for f in *.!\(ext\); do echo $f; done'

    Resultado:

    *.!(ext)
    

     

  3. bash -c 'for f in *.!$0; do echo $f; done' '(ext)'

    Resultado:

    *.!(ext)
    

     

  4. bash -c 'for f in "*.!(ext)"; do echo $f; done'

    Resultado:

    *.!(ext)
    

Responder1

Para usar um padrão globbing estendido no bash, você terá que habilitar a extglobopção shell de uma forma ou de outra.

A maneira mais fácil de fazer isso para um bash -cscript in-line é definir a opção shell com a -Oopção na linha de comando:

bash -O extglob -c 'script code here'

Você também pode simplesmente ligarshopt -s extglob dentro do roteiro, mas você deve garantir que isso seja feito em uma linha separada, pois altera a maneira como o shell analisa o código (modifica a sintaxe do shell):

bash -c 'shopt -s extglob
         script code here'

Quanto à sua tarefa real de imprimir todos os nomes que não terminam com a string .ext:

bash -O extglob -O dotglob -O nullglob -c 'printf "%s\n" !(*.ext)'

Ao definir adicionalmente as opções dotglobe, nullglobo script corresponderá aos nomes ocultos e imprimirá uma única linha vazia se não houver correspondências (em vez de imprimir o padrão não expandido).

Observe que seu padrão *.!(ext)excluiria nomes de arquivos que terminam em ext(não apenas .ext)enomes de arquivos que não contêm um ponto.

informação relacionada