我想使用ghostscript压缩给定目录及其子目录中的所有pdf文件。
我被困find在循环中按文件名(包括空格)使用命令。
这是我针对的一些示例代码:
pdffiles=$(find /path/to/directory -type f -name *.pdf)
for file in pdffiles; do
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dBATCH -dQUIET -sOutputFile=new_$file $file;
rm $file;
mv new_$file $file;
done;
Run Code Online (Sandbox Code Playgroud)
知道如何解决空间问题吗?有一个更好的方法吗?
我根据您的精彩回复重构了我的脚本\n并且运行得很好:)
\n这是重构、改进的代码\n,其中包含日志记录、参数和其他一些内容。\xc2\xa0\n我\'m\xc2\xa0始终对我的代码的改进持开放态度。
\n#!/bin/bash\n \n## Script to compress PDF Files using Ghostscript incl. subdirs\n## Copyright (C) 2016 Maximilian Fries - All Rights Reserved\n## Contact: maxfries@t-online.de\n## Last revised 2016-07-29\n\n# Usage\n# ./pdf-compress.sh [screen|ebook|prepress|default] [verbose]\n\n# Variables and preparation\n{\n count=0\n success=0\n successlog=./success.tmp\n gain=0\n gainlog=./gain.tmp\n pdfs=$(find ./ -type f -name "*.pdf")\n total=$(echo "$pdfs" | wc -l)\n log=./log\n verbose="-dQUIET"\n mode="prepress"\n echo "0" | tee $successlog $gainlog > /dev/null\n}\n\n# Are there any PDFs?\nif [ "$total" -gt 0 ]; then\n\n #Parameter Handling & Logging\n {\n echo "-- Debugging for Log START --"\n echo "Number of Parameters: $#"\n echo "Parameters are: $*"\n echo "-- Debugging for Log END --"\n } >> $log\n\n # Only compression-mode set\n if [ $# -eq 1 ]; then\n mode="$1"\n fi\n\n # Also Verbose Level Set\n if [ $# -eq 2 ]; then\n mode="$1"\n verbose=""\n fi\n\n echo "$pdfs" | while read -r file\n do\n ((count++))\n echo "Processing File #$count of $total Files" | tee -a $log\n echo "Current File: $file "| tee -a $log\n gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS="/$mode" -dNOPAUSE \\\n -dBATCH $verbose -sOutputFile="$file-new" "$file" | tee -a $log\n \n sizeold=$(wc -c "$file" | cut -d\' \' -f1)\n sizenew=$(wc -c "$file-new" | cut -d\' \' -f1)\n difference=$((sizenew-sizeold))\n\n # Check if new filesize is smaller\n if [ $difference -lt 0 ]\n then\n rm "$file"\n mv "$file-new" "$file"\n printf "Compression was successful. New File is %\'.f Bytes smaller\\n" \\\n $((-difference)) | tee -a $log\n ((success++)) \n echo $success > $successlog\n ((gain-=difference))\n echo $gain > $gainlog\n else\n rm "$file-new"\n echo "Compression was not necessary" | tee -a $log\n fi\n\n done\n\n # Print Statistics\n printf "Successfully compressed %\'.f of %\'.f files\\n" $(cat $successlog) $total | tee -a $log\n printf "Saved a total of %\'.f Bytes\\n" $(cat $gainlog) | tee -a $log\n\n rm $successlog $gainlog\n\nelse\n echo "No PDF File in Directory"\nfi\nRun Code Online (Sandbox Code Playgroud)\n
单行脚本也是一种选择:
find -type f -name "*.pdf" -exec bash -c 'gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dBATCH -dQUIET -sOutputFile="new.pdf" "{}"; rm "{}"; mv "new.pdf" "{}";' {} \;
Run Code Online (Sandbox Code Playgroud)
你的循环最好写成
find ... | while read -r file
Run Code Online (Sandbox Code Playgroud)
但是您需要确保在循环内引用文件名。所以我们最终得到
find /path/to/directory -type f -name *.pdf | while read -r file
do
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dBATCH -dQUIET -sOutputFile="new_$file" "$file"
rm "$file"
mv "new_$file" "$file"
done
Run Code Online (Sandbox Code Playgroud)
(另请注意,所有这些;都不需要)。
现在这个循环有潜在的文件所有权/权限问题,但这是另一个问题:-)