脚本以使用命令 (ls) 的输出并在另一个命令中使用它

alb*_*ett 6 shell io-redirection

我有一组要转换为 epub 的 pdf 文件。我知道 Calibre 的命令ebook-convert可以解决问题(我可以补充一下)。但是我有不止一个文件。

我希望能够运行一个脚本,该脚本运行ls > file然后某些内容通过所述文件运行并解析它,因此每个条目都是一个变量。然后使用变量 to 作为输入文件ebook-convert;并以某种方式将变量作为输出文件,但将 a 附加.epub到文件名的末尾?

Gil*_*il' 10

我将扩展jasonwryan的答案,它解释了什么,而不是如何或为什么。

您可以将一个命令的输出用作另一个命令的参数。这称为命令替换

some_text='Hello, world'
uppercased="$(echo "$some_text" | tr a-z A-Z)"
echo "Now, it's $uppercased"
Run Code Online (Sandbox Code Playgroud)

然而,它$(ls …)之所以可怕,有两个原因:

  • 不要解析 ls 的输出。它不是设计为可解析的。
  • "$(some-command)"给你一个字符串,它是该命令的输出。如果您有一个返回元素列表的命令,则需要将该字符串解析为单个元素。除非您能找到一个简单的分隔符,否则这既繁琐又不可靠。对于文件名,您无法轻松找到分隔符,因为大多数 unice 上的文件名都可以包含每个字符?。

请注意,如果您编写$(some-command)而不是"$(some-command)",则命令的输出将拆分为单词并进行通配。在您理解上一句之前,请始终在命令替换周围加上双引号。当您确实理解时,请始终使用双引号,除非您知道为什么不能使用双引号。

幸运的是,生成与特定模式匹配的文件列表是 shell 内置的一项功能。这就是所谓的通配符

echo *.pdf
Run Code Online (Sandbox Code Playgroud)

要对多个文件进行操作,请使用循环。

for x in *.pdf; do …; done
Run Code Online (Sandbox Code Playgroud)

剩下的障碍是生成目标文件的名称。shell 有一些简单的文本操作命令,其中包括${foo%SUFFIX}删除后缀的变量的值。(还有${foo#PREFIX}。)

for x in *.pdf; do
  ebook-convert "$x" "${x%.pdf}.epub"
done
Run Code Online (Sandbox Code Playgroud)

注意变量替换周围的双引号。原因与命令替换相同。

? 除了空字符,但大多数 shell 无法处理这些。


jas*_*yan 8

这可能是一种更简单的方法:

for file in *.pdf; do
    ebook-convert "$file" "${file%.pdf}.epub"
done
exit 0
Run Code Online (Sandbox Code Playgroud)