web-dev-qa-db-ja.com

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は最初に/をもたらすため、processed $ 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.

何らかの理由で、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"

ループが機能しない理由はありますか?
P.S。パーミッションエラーがないことを確認するために、今のところすべてのディレクトリは777です。

1
Umer

数回テストした後、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
0
Haxiel

問題

デフォルトでは、find-printアクションを実行します。

 -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が含まれ、式全体が連結された2つのパスに展開されます。

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

本当; print format標準出力で、 `\ 'エスケープと`%'ディレクティブを解釈します。

[...]

        \n     Newline.

        %f     File's name with any leading directories removed (only
                 the last element).

相対名を使用する

または(入力ファイルが異なるディレクトリにある場合)、ディレクトリパスのsomeを削除する必要があります。あなたは例えばを使うことができます。そのための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番目の/までのすべてが削除されます。ただし、入力ツリーの構造に一致する新しい出力ディレクトリの作成は処理されません。

1
JigglyNaga