Перебрать все файлы в папке с помощью bash

Перебрать все файлы в папке с помощью bash

У меня в папке есть несколько файлов markdown, которые я хотел бы преобразовать в html с помощью pandoc.

Команда, которую я обычно использую, это

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

где Atten.mdимя типичного файла markdown. Однако я хотел бы перебрать все файлы и преобразовать .md в .html, как это сделано выше. Как это сделать в bash или zsh?

решение1

С 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 {} \;

Он должен работать в Bash, Zsh и многих других оболочках. Единственная задача внешней оболочки — запуск findс правильными аргументами.

Эта версия создает один процесс shдля обработки как можно большего количества файлов ( shпри необходимости будут созданы дополнительные процессы):

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 {} +

Примечания:

  • Внутренняя оболочка вызывается только потому, что нам нужно удалить старое расширение. Если бы это не было требованием, то решение с , … -exec pandoc … -o {}.html {} \;вероятно, сработало бы. "Вероятно", потому что POSIX требует findзаменить один единственный {}. Это "любезность" реализации, которую findвы используете, если что-то еще заменяется (например, {}.htmlили второе появление {}).
  • -execdirбыло бы лучше вместо , -execно это не POSIX.
  • -execdirпозволит нам использовать ./"$1"вместо "$1"(соответственно: ./"$f"вместо "$f"), чтобы предотвратить его интерпретацию pandocкак вариант. Другой подход заключается в--но я не знаю, pandocподдерживает ли это. Я думаю, в вашем случае "$1"не может расширяться до чего-либо, начинающегося с , -потому что это должно начинаться с path/to/dir, и если бы path/to/dirначалось с -, то это было бы неправильно истолковано findизначально. В целом, хотя это беспокойство обосновано.
  • При pandocвызове я переместил операнд в конец только из-за своей любви к наиболее распространенному порядку command -options operands.

  • Решение рекурсивное. Чтобы сделать его нерекурсивным, укажите -maxdepth 1. Если ваш findне поддерживает, -maxdepthто изучитеэтотили удалить findи позволить внешней оболочке перебрать файлы:

    # 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 )
    

    Примечания, относящиеся к приведенному выше коду:

    • Подоболочка предназначена для cdработы без влияния на текущую оболочку.
    • Если cdпо какой-то причине не получится, то остальное не будет выполнено. Это хорошая практика.
    • ./*.mdвместо простого *.mdпредотвращает "$f"его интерпретацию в качестве варианта в дальнейшем.
    • ./.*.mdдобавлен, поскольку ./*.mdне соответствует dotfiles.
    • [ -f "$f" ]чтобы предотвратить
      • вызов pandocкаталогов, специальных файлов и т.п.;
      • вызов pandocнесуществующего ./*.md(или ./.*.md), когда ничто не соответствует шаблону.
    • Zsh несколько отличается. Код должен работать, shхотя и поскольку подоболочка полезна в любом случае, то не будет большой разницы, если вы вызовете shявно из любой нормальной оболочки:

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

решение2

Вы должны использовать findи его -exec(см.человек находит):

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

Или, может быть -execdir.

решение3

Вы можете выполнить итерацию файла с помощью for:

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

Связанный контент