使用 bash 迭代文件夹中的所有文件

使用 bash 迭代文件夹中的所有文件

我的文件夹中有一堆 markdown 文件,我想使用 pandoc 将其转换为 html。

我通常使用的命令是

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 和许多其他 shell 中工作。外壳的唯一工作是使用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 )
    

    针对上述代码的具体注释:

    • 子 shell 的cd作用是不影响当前 shell 的。
    • 如果cd因任何原因失败,则其余部分将不会被执行。这是一个很好的做法。
    • ./*.md而不是简单的*.md防止"$f"稍后被解释为选项。
    • ./.*.md./*.md由于与点文件不匹配而被添加。
    • [ -f "$f" ]是为了防止
      • 调用pandoc目录、特殊文件等;
      • 当没有任何东西与模式匹配时,调用pandoc不存在./*.md(或)。./.*.md
    • Zsh 稍有不同。不过代码应该可以工作,而且因为子 shell 无论如何都是有用的,所以如果你从任何正常的 shell 中显式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

相关内容