我有以下文件结构
|--folder1
| |---1.markdown
|--folder2
| |---2.markdown
|--folder3
| |---3.markdown
...
我想将 markdown 文件转换为 HTML 文件,以便将 HTML 文件创建到每个特定文件夹中。例如1.html
应该位于folder1
。
我可以通过以下方式转换一个 markdown 文件
markdown.py-2.6 1.markdown > 1.html
所以我们应该以某种方式能够获取每个 HTML 文件前面后缀之前的单词。
如何有效地将多个 markdown 文件转换为其对应的 HTML 文件?
答案1
现有的基于 bash 的答案将会破坏名称中带有空格的文件,并调用不必要的外部命令来启动。
假设 bash 4+ 可用(可能可用,请检查bash --version
),您可以设置 globstar 进行递归通配符:
shopt -s globstar
for f in ./**/*.markdown; do markdown.py-2.6 "$f" > "${f%.markdown}.html"; done
这也可以通过 find 来完成;为了绝对的防弹,您应该使用空字节分隔符:
find . -name '*.markdown' -print0 | while read -d $'\0' f; do
markdown.py-2.6 "$f" > "${f%.markdown}.html"
done
这个特殊的问题也可以使用 find 的选项来解决-exec
,如下所示:
find . -name '*.markdown' -exec bash -c 'markdown.py-2.6 "$0" > "${0%.markdown}.html" '{}' \;
然而,这并不容易扩展到多行脚本。
答案2
你可以用一个小的 bash 脚本来完成此操作:
for i in `find . -name "*.markdown"`; do
markdown.py-2.6 $i > `dirname $i`/`basename -s .markdown $i`.html
done
答案3
你可能会发现在 bash 中执行此操作更容易(因为一旦你理解了语法,它就只有一两行),但为了记录,这里是如何在 Python 中执行此操作的。你想使用两个函数os.walk, 和fnmatch.fnmatch以匹配每个目录中所需的文件。如下所示:
#!/usr/bin/env python
import os, sys
from fnmatch import fnmatch
if len(sys.argv) != 2:
print "Usage:", sys.argv[0], "<directory>"
sys.exit()
markdown = # <path to markdown.py>
directory = sys.argv[1]
for path, directory, files in os.walk(directory):
for file in files:
if fnmatch(file, "*.html"):
html_file = "%s/%s" % (path, file)
markdown_file = html_file.replace(".html", ".markdown")
os.system("python %s %s > %s" % (markdown, markdown_file, html_file))
需要记住的主要事项:
- 该
os.walk
函数遍历目录结构(使用生成器)。它返回三个变量:- 当前目录 (
path
) - 当前目录中找到的目录列表 (
directories
)。在这种情况下,您不需要它。 - 当前目录中找到的文件列表 (
files
)。您做需要这个。
- 当前目录 (
- 该
fnmatch.fnmatch
函数获取文件列表并告诉您它是否与模式匹配。这是一个 shell “glob” 模式,而不是正则表达式。您可以在此处使用正则表达式,但fnmatch
对于像这样的简单情况来说,这样做更简单。
请注意,您需要指定 markdown 脚本的路径。更好的方法是不使用它,os.system
而是导入 markdown 模块并调用它的主要函数,但这适用于非 Python 程序。(另外,我不知道那个函数到底是什么 :)。
答案4
jamuraa 的答案的修改:
for i in `find . -name "*.markdown"`; do
pushd `dirname $i`
markdown.py-2.6 $i > `basename -s .markdown $i`.html
popd
done