
У меня в папке есть несколько файлов 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