linux 通过书签拆分PDF?

1bqhqjot  于 2023-06-21  发布在  Linux
关注(0)|答案(5)|浏览(112)

我是处理单个PDF文件,每个文件都是通过“合并”多个PDF文件创建的。每个合并的PDF都有PDF部件开始显示的位置,并带有书签。
有没有什么方法可以通过脚本自动将其按书签分割?
我们只有书签来表示各个部分,而没有页码,因此我们需要从书签中推断页码。Linux工具是最好的。

nxowjjhe

nxowjjhe1#

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
xmakbtuz

xmakbtuz2#

有一个用Java编写的名为Sejda的命令行工具,您可以在其中找到splitbybookmarks命令,该命令完全可以执行您所要求的操作。它是Java,所以它运行在Linux上,作为一个命令行工具,你可以写脚本来做这件事。
免责声明
我是作者之一

uujelgoq

uujelgoq3#

你有像pdf-split这样的程序可以为你做到这一点:
A-PDF Split是一个非常简单, lightning 般快速的桌面实用程序,可让您将任何Acrobat PDF文件拆分为较小的PDF文件。它提供了完整的灵活性和用户控制方面的文件是如何分割和分割输出文件是如何唯一命名。A-PDF Split为您的大文件如何拆分提供了多种选择-按页面,按书签和按奇数/偶数页面。您甚至可以提取或删除PDF文件的一部分。A-PDF拆分还提供了高级定义的拆分,可以保存并在以后导入,以用于重复的文件拆分任务。A-PDF Split代表了文件拆分的最终灵活性,以满足各种需求。
A-PDF Split可处理受密码保护的PDF文件,并可将各种PDF安全功能应用于拆分输出文件。如果需要,您可以使用A-PDF Merger等实用程序将生成的拆分文件与其他PDF文件重新组合,以形成新的复合PDF文件。
A-PDF Split不需要Adobe Acrobat,并生成与Adobe Acrobat Reader版本5及以上兼容的文档。
编辑 *
如果你不想付费的话,我还找到了一个免费的开源程序Here

yrefmtwq

yrefmtwq4#

下面是我用来完成这个任务的一个小Perl程序。Perl并不特别;它只是pdftk的一个 Package 器,用来解释dump_data输出,将其转换为要提取的页码:

#!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;
    }
rkkpypqq

rkkpypqq5#

我编写了一个Python script,使用pdftk将PDF在具有特定名称的书签处一分为二。此脚本保留两个输出PDF中的书签。

相关问题