我有一组 pdf 文件,想转换为 epub。我知道 Calibre 的命令ebook-convert
可以解决问题(我可以补充一下)。但是我有不止一个文件。
我希望能够运行一个脚本,ls > file
然后运行某个文件并解析它,以便每个条目都是一个变量。然后使用变量 to 作为ebook-convert
;的输入文件并以某种方式将变量作为输出文件,但将 a 附加.epub
到文件名的末尾?
答案1
我将扩展杰森·瑞恩的答案,解释了是什么,但没有解释如何或为什么。
您可以使用一个命令的输出作为另一个命令的参数。这就是所谓的命令替换。
some_text='Hello, world'
uppercased="$(echo "$some_text" | tr a-z A-Z)"
echo "Now, it's $uppercased"
然而,这很可怕,有两个原因:$(ls …)
- 不解析 ls 的输出。它不是被设计为可解析的。
"$(some-command)"
给你一个字符串,它是该命令的输出。如果您有一个返回元素列表的命令,则需要将该字符串解析为单个元素。除非你能找到一个简单的分隔符,否则这是繁琐且不可靠的。对于文件名,您无法轻松找到分隔符,因为大多数 unice 上的文件名可以包含每个字符⁰。
请注意,如果您编写$(some-command)
而不是"$(some-command)"
,则命令的输出将被拆分为单词并进行通配。在您理解前一句之前,请始终在命令替换两边加上双引号。当您确实理解时,请始终添加双引号,除非您知道为什么不能添加双引号。
幸运的是,生成与特定模式匹配的文件列表是 shell 中内置的一项功能。它被称为通配。
echo *.pdf
要对多个文件执行操作,可以使用循环。
for x in *.pdf; do …; done
剩下的障碍是生成目标文件的名称。 shell 有一些简单的文本操作命令,其中包括${foo%SUFFIX}
获取删除后缀的变量的值。 (还有${foo#PREFIX}
。)
for x in *.pdf; do
ebook-convert "$x" "${x%.pdf}.epub"
done
请注意变量替换周围的双引号。原因与命令替换相同。
⁰除了空字符,但大多数 shell 无法处理这些。
答案2
这可能是一个更简单的方法:
for file in *.pdf; do
ebook-convert "$file" "${file%.pdf}.epub"
done
exit 0
答案3
一句话回答,具有转换运行的轻微优势平行线:
parallel ebook-convert {} {.}.epub ::: *.pdf
我已经习惯不使用for 循环不再在壳里了。它们都可以整齐地替换为GNU 并行。