我打算递归地压缩一个文件夹中的几千个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
操作:
真的;在标准输出上打印完整的文件名,后跟换行符。
“完整文件名”意味着您将看到每个文件的绝对路径:
/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