递归压缩所有pdf文件

Mok*_*oka 5 shell bash find

我想使用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)

知道如何解决空间问题吗?有一个更好的方法吗?

Mok*_*oka 5

我根据您的精彩回复重构了我的脚本\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\n
Run Code Online (Sandbox Code Playgroud)\n


jef*_*ill 5

单行脚本也是一种选择:

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)


Ste*_*ris 3

你的循环最好写成

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)

(另请注意,所有这些;都不需要)。

现在这个循环有潜在的文件所有权/权限问题,但这是另一个问题:-)