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;
공간 문제를 해결하는 방법을 알고 계십니까? 더 좋은 방법이 있나요?
답변1
한 줄짜리 스크립트도 옵션입니다.
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" "{}";' {} \;
답변2
귀하의 훌륭한 답변을 바탕으로 스크립트를 리팩터링했는데 훌륭하게 작동합니다 :)
이는 로깅, 매개변수 및 기타 몇 가지 사항을 포함하여 리팩터링되고 개선된 코드입니다. 나는 항상 내 코드를 개선하는 데 관심이 있습니다.
#!/bin/bash
## Script to compress PDF Files using Ghostscript incl. subdirs
## Copyright (C) 2016 Maximilian Fries - All Rights Reserved
## Contact: [email protected]
## Last revised 2016-07-29
# Usage
# ./pdf-compress.sh [screen|ebook|prepress|default] [verbose]
# Variables and preparation
{
count=0
success=0
successlog=./success.tmp
gain=0
gainlog=./gain.tmp
pdfs=$(find ./ -type f -name "*.pdf")
total=$(echo "$pdfs" | wc -l)
log=./log
verbose="-dQUIET"
mode="prepress"
echo "0" | tee $successlog $gainlog > /dev/null
}
# Are there any PDFs?
if [ "$total" -gt 0 ]; then
#Parameter Handling & Logging
{
echo "-- Debugging for Log START --"
echo "Number of Parameters: $#"
echo "Parameters are: $*"
echo "-- Debugging for Log END --"
} >> $log
# Only compression-mode set
if [ $# -eq 1 ]; then
mode="$1"
fi
# Also Verbose Level Set
if [ $# -eq 2 ]; then
mode="$1"
verbose=""
fi
echo "$pdfs" | while read -r file
do
((count++))
echo "Processing File #$count of $total Files" | tee -a $log
echo "Current File: $file "| tee -a $log
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS="/$mode" -dNOPAUSE \
-dBATCH $verbose -sOutputFile="$file-new" "$file" | tee -a $log
sizeold=$(wc -c "$file" | cut -d' ' -f1)
sizenew=$(wc -c "$file-new" | cut -d' ' -f1)
difference=$((sizenew-sizeold))
# Check if new filesize is smaller
if [ $difference -lt 0 ]
then
rm "$file"
mv "$file-new" "$file"
printf "Compression was successful. New File is %'.f Bytes smaller\n" \
$((-difference)) | tee -a $log
((success++))
echo $success > $successlog
((gain-=difference))
echo $gain > $gainlog
else
rm "$file-new"
echo "Compression was not necessary" | tee -a $log
fi
done
# Print Statistics
printf "Successfully compressed %'.f of %'.f files\n" $(cat $successlog) $total | tee -a $log
printf "Saved a total of %'.f Bytes\n" $(cat $gainlog) | tee -a $log
rm $successlog $gainlog
else
echo "No PDF File in Directory"
fi
답변3
귀하의 루프는 다음과 같이 작성하는 것이 가장 좋습니다.
find ... | while read -r file
하지만 루프 내에서 파일 이름을 참조하는지 확인해야 합니다. 그래서 우리는 결국
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
(또한 이 중 어느 것도 ;
필수 사항이 아닙니다.)
이제 이 루프에는 잠재적인 파일 소유권/권한 문제가 있지만 이는 또 다른 문제입니다. :-)