11

複数の PDF を「マージ」して作成された単一の PDF を処理します。マージされた各 PDF には、PDF パーツの開始位置がブックマーク付きで表示されます。

これをスクリプトを使用してブックマークで自動的に分割する方法はありますか?

ページ番号ではなく、パーツを示すブックマークしかないため、ブックマークからページ番号を推測する必要があります。Linux ツールが最適です。

4

4 に答える 4

21

pdftk を使用して、PDF ファイルを分割し、ブックマークのページ番号を抽出できます。

ブックマークのページ番号を取得するには

pdftk in.pdf dump_data

スクリプトに出力からページ番号を読み取らせます。

次に使用します

pdftk in.pdf cat A-B output out_A-B.pdf

A から B までのページを out_A-B.pdf に取得します。

スクリプトは次のようになります。

#!/bin/bash

infile=$1 # input pdf
outputprefix=$2

[ -e "$infile" -a -n "$outputprefix" ] || exit 1 # Invalid args

pagenumbers=( $(pdftk "$infile" dump_data | \
                grep '^BookmarkPageNumber: ' | cut -f2 -d' ' | uniq)
              end )

for ((i=0; i < ${#pagenumbers[@]} - 1; ++i)); do
  a=${pagenumbers[i]} # start page number
  b=${pagenumbers[i+1]} # end page number
  [ "$b" = "end" ] || b=$[b-1]
  pdftk "$infile" cat $a-$b output "${outputprefix}"_$a-$b.pdf
done
于 2012-04-10T09:20:10.373 に答える
5

Sejdaと呼ばれる Java で記述されたコマンド ライン ツールがあり、要求したことを正確に実行するコマンドを見つけることができますsplitbybookmarks。これは Java であるため、Linux 上で実行され、スクリプトを記述できるコマンド ライン ツールです。

免責事項
私は著者の一人です

于 2012-12-18T23:47:10.330 に答える
3

それを行うことができるpdf-splitのように構築されたプログラムがあります:

A-PDF Split は、Acrobat pdf ファイルを小さな pdf ファイルに分割できる、非常にシンプルで非常に高速なデスクトップ ユーティリティ プログラムです。ファイルの分割方法と分割された出力ファイルに一意の名前を付ける方法に関して、完全な柔軟性とユーザー制御を提供します。A-PDF 分割は、大きなファイルをページごと、ブックマークごと、奇数/偶数ページごとに分割するためのさまざまな方法を提供します。PDF ファイルの一部を抽出または削除することもできます。A-PDF 分割は、繰り返しファイル分割タスクで使用するために保存して後でインポートできる、高度に定義された分割も提供します。A-PDF Split は、あらゆるニーズに対応する究極のファイル分割柔軟性を備えています。

A-PDF Split は、パスワードで保護された PDF ファイルで動作し、分割された出力ファイルにさまざまな PDF セキュリティ機能を適用できます。必要に応じて、A-PDF Merger などのユーティリティを使用して、生成された分割ファイルを他の PDF ファイルと再結合し、新しい複合 PDF ファイルを作成できます。

A-PDF Split は Adob​​e Acrobat を必要とせず、Adobe Acrobat Reader バージョン 5 以降と互換性のあるドキュメントを生成します。

編集*

支払いたくない場合は、ここで無料のオープン ソース プログラムも見つけました。

于 2010-04-08T17:00:11.307 に答える
1

これは、私がタスクに使用する小さな Perl プログラムです。Perl は特別なものではありません。dump_data出力を解釈して抽出するページ番号に変換するのは、pdftk の単なるラッパーです。

#!perl
use v5.24;
use warnings;

use Data::Dumper;
use File::Path qw(make_path);
use File::Spec::Functions qw(catfile);

my $pdftk = '/usr/local/bin/pdftk';
my $file = $ARGV[0];
my $split_dir = $ENV{PDF_SPLIT_DIR} // 'pdf_splits';

die "Can't find $ARGV[0]\n" unless -e $file;

# Read the data that pdftk spits out.
open my $pdftk_fh, '-|', $pdftk, $file, 'dump_data';

my @chapters;
while( <$pdftk_fh> ) {
    state $chapter = 0;
    next unless /\ABookmark/;

    if( /\ABookmarkBegin/ ) {
        my( $title ) = <$pdftk_fh> =~ /\ABookmarkTitle:\s+(.+)/;
        my( $level ) = <$pdftk_fh> =~ /\ABookmarkLevel:\s+(.+)/;

        my( $page_number ) = <$pdftk_fh> =~ /\BookmarkPageNumber:\s+(.+)/;

        # I only want to split on chapters, so I skip higher
        # level numbers (higher means more nesting, 1 is lowest).
        next unless $level == 1;

        # If you have front matter (preface, etc) then this numbering
        # will be off. Chapter 1 might be called Chapter 3.
        push @chapters, {
            title         => $title,
            start_page    => $page_number,
            chapter       => $chapter++,
            };
        }
    }

# The end page for one chapter is one before the start page for
# the next chapter. There might be some blank pages at the end
# of the split for PDFs where the next chapter needs to start on
# an odd page.
foreach my $i ( 0 .. $#chapters - 1 ) {
    my $last_page = $chapters[$i+1]->{start_page} - 1;
    $chapters[$i]->{last_page} = $last_page;
    }
$chapters[$#chapters]->{last_page} = 'end';

make_path $split_dir;
foreach my $chapter ( @chapters ) {
    my( $start, $end ) = $chapter->@{qw(start_page last_page)};

    # slugify the title so use it as a filename
    my $title = lc( $chapter->{title} =~ s/[^a-z]+/-/gri );

    my $path = catfile( $split_dir, "$title.pdf" );
    say "Outputting $path";

    # Use pdftk to extract that part of the PDF
    system $pdftk, $file, 'cat', "$start-$end", 'output', $path;
    }
于 2020-02-14T02:20:27.657 に答える