嘗試通過循環遞歸地使用 ghostscript 壓縮 pdf 時出錯
我打算遞歸壓縮文件夾中的幾千個 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
(處理 $ file is used because $ 文件在開始時帶有 / 並且我也嘗試過處理/$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.
出於某種原因,它在 path/to/output/path/to/input 中尋找 pdf。我嘗試更改為 ./ 連結而不是 / 但無濟於事。
如果我自己執行以下命令,它會很好地輸出壓縮的 pdf
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/prepress -dNOPAUSE -dBATCH -dQUIET -sOutputFile="/home/user/processed/output.pdf" "input.pdf"
任何想法為什麼循環不起作用?
PS所有目錄現在都是777,以確保沒有任何權限錯誤
經過幾次測試,我觀察到 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
問題
預設情況下,
find
執行真的; 在標準輸出上列印完整的文件名,後跟換行符。
“完整文件名”意味著您將看到每個文件的絕對路徑:
/home/user/original/test001.pdf /home/user/original/test002.pdf ... /home/user/original/test999.pdf
所以當你使用
gs -sOutputFile="/home/user/processed$file"
…在循環內,變數
$file
contains/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 個。但是,它不會處理新輸出目錄的創建以匹配輸入樹的結構。