【问题标题】:Using Zsh and QPDF to decrypt multiple PDFs使用 Zsh 和 QPDF 解密多个 PDF
【发布时间】:2020-01-21 23:43:42
【问题描述】:

从这个答案https://stackoverflow.com/a/59688271/7577919 我能够使用这个 bash 脚本来解密多个 PDF:

temp=`ls`; 
for each in $temp;
do qpdf --decrypt --replace-input $each;  
done

但是,我最初尝试在 Zsh 中执行此操作(在 MacOS 10.15 Catalina 中鼓励这样做),但无法做到。它给出了output: File name too long的错误

Bash 和 Zsh 中的 for 循环之间有什么区别,我将如何编写合适的 Zsh 脚本?

【问题讨论】:

  • for i in *; do qpdf --decrypt --replace-input "$i"; done 会起作用吗? (注意引号)
  • 是的,这似乎可行。为什么?为什么它不需要temp=`ls`
  • @dibery :如果我们很挑剔,您的解决方案并不完全等同。在没有文件的目录的情况下,您的解决方案会给出一条错误消息并 seteach 执行单个星号,而 ls 将扩展为空字符串。
  • @CTHall 我猜文件名中有一些空格。您可以通过在脚本之前发出 set -x 来调试它,以查看哪个文件是导致此错误的原因。星号扩展到该目录中的所有文件(如果有任何文件)。
  • @user1934428 zsh 默认情况下不会将不匹配的模式视为文字字符串;它引发了一个错误。 bashzsh 都可以配置为将不匹配的模式视为空序列(不是文字空字符串),这样就不会进入循环。

标签: bash for-loop zsh qpdf


【解决方案1】:

for循环没有区别,只是变量扩展的方式不同。考虑这个程序:

x='a b'
for v in $x
do
  echo $v
done

在 bash 中,$x 将字拆分为 2 个参数,因此循环将执行两次,一次用于 a,一次用于b。在 zsh 中,$x 不会进行分词,循环将执行一次,值为 a b。展开参数时,这种差异无处不在。

在您的情况下,循环执行一次,each 保存ls 语句的完整输出。

当然,在你的情况下,在 zsh 中将循环编写为更简单

for each in *(N)

但如果你真的需要一个变量,我会使用一个数组:

temp=(*(N))

如果没有文件,通配符后面的N-标志会确保您得到一个空字符串而不是错误消息。

如果您还想捕获点文件(类似于 ls -A 的做法),请改用 (ND)

【讨论】:

  • 我有一个只有 pdf 的文件夹,但如果我有一个包含混合文件的文件夹并且只需要 pdf 怎么办?在 bash 中,我可以设置 `temp=ls *.pdf`,但是在 Zsh 中我该怎么做呢?
  • 我不明白您为什么要为您的具体简单案例使用 temp 变量,但如果您这样做,它很简单:temp=( *.pdf(N) )。在 bash 中,您将执行 temp=( *.pdf )。不要忘记,在使用数组时,您可以在 zsh 中使用 for f in ${temp[@]} 和在 bash 中使用 for f in "${temp[@]}" 循环。
  • 我想专注于原始帖子。感谢您的帮助。
【解决方案2】:

由于parsing the result of ls is not encouraged,可能不建议使用ls 来获取pdf 文件名。相反,您可以使用find

find . -name '*.pdf' -exec qpdf --decrypt --replace-input "{}" \;

您可以通过将-maxdepth 1 添加到find 来限制当前目录中的pdf。

【讨论】:

    猜你喜欢
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 2020-10-18
    相关资源
    最近更新 更多