¿Cómo usar glob extendido con paréntesis en un comando pasado a `bash -c`?

¿Cómo usar glob extendido con paréntesis en un comando pasado a `bash -c`?

Estoy intentando utilizar un globo extendido con bash -c, pero no he encontrado una manera de hacerlo funcionar.

Cosas que he probado

  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)
    

Respuesta1

Para utilizar un patrón global extendido en bash, deberá habilitar la extglobopción Shell de una forma u otra.

La forma más sencilla de hacer esto para un script en línea bash -ces configurar la opción de shell con la -Oopción en la línea de comando:

bash -O extglob -c 'script code here'

También puedes simplemente llamarshopt -s extglob dentro del guión, pero debe asegurarse de que esto se haga en una línea separada, ya que cambia la forma en que el shell analiza el código (modifica la sintaxis del shell):

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

En cuanto a su tarea real de imprimir todos los nombres que no terminan con la cadena .ext:

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

Al configurar adicionalmente las opciones dotgloby nullglob, el script coincidiría con nombres ocultos e imprimiría una sola línea vacía si no hay coincidencias (en lugar de imprimir el patrón no expandido).

Tenga en cuenta que su patrón *.!(ext)excluiría los nombres de archivos que terminen en ext(no solo .ext)ynombres de archivos que no contienen un punto.

información relacionada