使用 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而不是 plain*.md可以防止"$f"稍後被解釋為選項。
    • ./.*.md被加入是因為./*.md與點文件不符。
    • [ -f "$f" ]是為了防止
      • 呼叫pandoc目錄、特殊檔案等;
      • 當沒有任何內容與模式匹配時呼叫pandocfor 不存在./*.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

相關內容