Iterar sobre todos los archivos en la carpeta con bash

Iterar sobre todos los archivos en la carpeta con bash

Tengo un montón de archivos de rebajas en mi carpeta que me gustaría convertir a html con pandoc.

El comando que suelo utilizar es

pandoc Atten.md -f markdown -t html --css pandoc.css -o Atten.html

¿Dónde Atten.mdestá el nombre de un archivo de rebajas típico? Sin embargo, me gustaría iterar sobre todos los archivos y convertir .md a .html como se hizo anteriormente. ¿Cómo hago eso en bash o zsh?

Respuesta1

Con find:

find path/to/dir -name "*.md" -type f -exec sh -c '
      pandoc -f markdown -t html --css pandoc.css -o "${1%.*}.html" "$1"
   ' find-sh {} \;

Debería funcionar en Bash, Zsh y muchos otros shells. El único trabajo del caparazón exterior es ejecutar findcon los argumentos adecuados.

Esta versión genera uno único shpara procesar tantos archivos como sea posible ( shse generarán más procesos si es necesario):

find path/to/dir -name "*.md" -type f -exec sh -c '
      for f; do
         pandoc -f markdown -t html --css pandoc.css -o "${f%.*}.html" "$f"
      done
   ' find-sh {} +

Notas:

  • El shell interno se invoca sólo porque necesitamos eliminar la extensión anterior. Si no fuera el requisito, entonces una solución … -exec pandoc … -o {}.html {} \;probablemente funcionaría. "Probablemente" porque POSIX requiere findreemplazar uno único {}. Es una "cortesía" de la findimplementación que utiliza, si se reemplaza algo más (como {}.htmlla segunda aparición de {}).
  • -execdiren lugar de -execsería mejor pero no es POSIX.
  • -execdirnos permitiría usarlo ./"$1"en lugar de "$1"(respectivamente: ./"$f"en lugar de "$f") para evitar que sea interpretado pandoccomo una opción. Otro enfoque es--pero no sé si pandoclo soporta. Creo que en su caso "$1"no se puede expandir a nada que comience con -porque debe comenzar con path/to/dir, y si path/to/dircomienza con entonces , en primer lugar, -se malinterpretaría con . findAunque en general esta preocupación es legítima.
  • En pandocla invocación moví el operando al final solo por mi afición hacia el orden más común de command -options operands.

  • La solución es recursiva. Para que sea no recursivo, especifique -maxdepth 1. Si findno lo apoyas, -maxdepthentonces estudia.esteo soltar findy dejar que el shell externo repita los archivos:

    # written for Bash
    ( cd path/to/dir || exit 125
    for f in ./*.md ./.*.md; do
        [ -f "$f" ] &&
        pandoc -f markdown -t html --css pandoc.css -o "${f%.*}.html" "$f"
    done )
    

    Notas específicas del código anterior:

    • El subshell está diseñado para cdfuncionar sin afectar el shell actual.
    • Si cdfalla por cualquier motivo, el resto no se ejecutará. Ésta es una buena práctica.
    • ./*.mden lugar de simple *.mdimpide "$f"que se interprete como una opción más adelante.
    • ./.*.mdse agrega porque ./*.mdno coincide con los archivos de puntos.
    • [ -f "$f" ]es para prevenir
      • invocar pandocdirectorios, archivos especiales y demás;
      • invocando pandocinexistente ./*.md(o ./.*.md) cuando nada coincide con el patrón.
    • Zsh es algo diferente. Sin embargo , el código debería funcionar shy, debido a que un subshell es útil de todos modos, no haría mucha diferencia si llamara shexplícitamente desde cualquier Shell sensato:

      sh -c 'cd path/to/dir || exit 125
             for …
             done '
      

Respuesta2

Debes usar findy su -exec(verhombre encontrar):

find YourDirectory -name \*.md | \
  while IFS= read fn; do \
  pandoc ${fn} -f markdown -t html --css pandoc.css -o ${fn%.md}.html ; done

O tal vez -execdir.

Respuesta3

Puede iterar el archivo con un for:

for item in *.md; do CONVERT_FILE_COMMAND $item "$(basename '$item' .md).html; done

información relacionada