问题

问题

我打算递归地压缩一个文件夹中的几千个PDF文件。

我尝试使用以下循环:

#!/bin/bash
find "/home/user/original" -type f -name *.pdf | while read -r file
do
  gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/prepress -dNOPAUSE -dBATCH -dQUIET -sOutputFile="/home/user/processed$file" "$file"
done

(使用processed$file是因为$file在开头带有一个/并且我也尝试过processed/$file)

无论如何,运行循环会出现以下错误:

GPL Ghostscript 9.26: **** Could not open the file /home/user/processed/home/user/original/test001.pdf .
**** Unable to open the initial device, quitting.

由于某种原因,它在路径/到/输出/路径/到/输入中寻找pdf。我尝试更改为 ./ 链接而不是 / 但无济于事。

如果我单独运行以下命令,它会很好地输出压缩的 pdf

gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/prepress -dNOPAUSE -dBATCH -dQUIET -sOutputFile="/home/user/processed/output.pdf" "input.pdf"

有什么想法为什么循环不起作用?
PS 现在所有目录都是 777 以确保没有任何权限错误

答案1

问题

默认情况下,find执行以下-print操作:

 -print

真的;在标准输出上打印完整的文件名,后跟换行符。

“完整文件名”意味着您将看到每个文件的绝对路径:

/home/user/original/test001.pdf
/home/user/original/test002.pdf
...
/home/user/original/test999.pdf

所以当你使用

gs -sOutputFile="/home/user/processed$file"

...在循环内部,变量$file包含/home/user/original/test001.pdf,并且整个表达式扩展到连接的两个路径:

gs -sOutputFile="/home/user/processed/home/user/original/test001.pdf"

您看到的错误消息反映了这一点:

Could not open the file /home/user/processed/home/user/original/test001.pdf

使用基本名称

如果您只需要文件的基本名称(因为所有文件都位于同一源文件夹中),您可以告诉find使用不同的输出格式。

find "/home/user/original" -type f -name *.pdf -printf '%f\n'
   -printf format

真的;打印格式在标准输出上,解释“\”转义符和“%”指令。

[...]

        \n     Newline.

        %f     File's name with any leading directories removed (only
                 the last element).

使用相对名称

或者(如果输入文件位于不同的目录中),您将需要修剪一些的目录路径。你可以使用例如。cut为了那个原因:

find "/home/user/original" -type f -name *.pdf | cut -d/ -f5- | while read -r file
do
    gs [...] -sOutputFile="/home/user/processed/$file" "/home/user/original/$file"

/这将删除输入的第 4 个之前的所有内容(包括第 4 个输入)。但是,它不会处理新输出目录的创建以匹配输入树的结构。

答案2

经过几次测试后,我观察到 Ghostscript 存在以下行为。当您将输出文件指定为 时/home/user/processed/home/user/original/test001.pdf,该gs命令预计通向该文件 ( /home/user/processed/home/user/original/) 的路径已存在。由于目标中当前不存在源中的文件夹结构,因此该命令会引发错误并显示无法打开目标文件。

要解决此问题,您可以首先使用以下命令重新创建文件夹结构:

cd /home/user/original
find . -type d -exec mkdir -p -- /home/user/processed/{} \;

完成此操作后,您可以运行脚本来生成 PDF 文件。我能够使用您的gs命令生成 PDF 文件,因此我假设它没有其他问题。

脚本完成后,如果您怀疑目的地有空目录,并且想要删除它们,请使用以下 find 命令:

find /home/user/processed/ -type d -empty -delete

相关内容