我正在动态生成PDF。如何使用shell脚本检查PDF中的页数?
没有任何额外的包:
strings < file.pdf | sed -n 's|.*/Count -{0,1}([0-9]{1,}).*|1|p'
| sort -rn | head -n 1
使用pdfinfo:
pdfinfo file.pdf | awk '/^Pages:/ {print $2}'
使用pdftk:
pdftk file.pdf dump_data | grep NumberOfPages | awk '{print $2}'
您还可以通过pdfinfo递归地求和所有PDF中的页面总数,如下所示:
find . -xdev -type f -name "*.pdf" -exec pdfinfo "{}" ";" |
awk '/^Pages:/ {n += $2} END {print n}'
imagemagik库提供了一个名为identify的工具,该工具与计算输出行相结合,可以获得您想要的。。。imagemagick是一个简单的安装在osx上的brew。
这里有一个功能强大的bash脚本,它将它捕获到一个shell变量中,并将其转储回屏幕。。。
#/bin/bash
pdfFile=$1
echo "Processing $pdfFile"
numberOfPages=$(/usr/local/bin/identify "$pdfFile" 2>/dev/null | wc -l | tr -d ' ')
#Identify gets info for each page, dump stderr to dev null
#count the lines of output
#trim the whitespace from the wc -l outout
echo "The number of pages is: $numberOfPages"
运行它的输出…
$ ./countPages.sh aSampleFile.pdf
Processing aSampleFile.pdf
The number of pages is: 2
$
pdftotext
实用程序将pdf文件转换为文本格式,在页面之间插入分页符。(又名:表单馈送字符$'f'
):
NAME
pdftotext - Portable Document Format (PDF) to text converter.
SYNOPSIS
pdftotext [options] [PDF-file [text-file]]
DESCRIPTION
Pdftotext converts Portable Document Format (PDF) files to plain text.
Pdftotext reads the PDF file, PDF-file, and writes a text file, text-file. If text-file is
not specified, pdftotext converts file.pdf to file.txt. If text-file is ´-', the text is
sent to stdout.
有许多组合可以解决您的问题,请选择其中一种:
1) pdftotext+grep:
$ pdftotext file.pdf - | grep -c $'f'
2) pdftotext+awk(v1):
$ pdftotext file.pdf - | awk 'BEGIN{n=0} {if(index($0,"f")){n++}} END{print n}'
3) pdftotext+awk(v2):
$ pdftotext sample.pdf - | awk 'BEGIN{ RS="f" } END{ print NR }'
4) pdftotext+awk(v3):
$ pdftotext sample.pdf - | awk -v RS="f" 'END{ print NR }'
希望有帮助!
这里有一个直接用于命令行的版本(基于pdfinfo):
for f in *.pdf; do pdfinfo "$f" | grep Pages | awk '{print $2}'; done
这是一个使用pdftoppm
的全面破解,它预装在Ubuntu上(至少在Ubuntu 18.04和20.04上测试过):
# for a pdf withOUT a password
pdftoppm mypdf.pdf -f 1000000 2>&1 | grep -o '([0-9]*).$'
| grep -o '[0-9]*'
# for a pdf WITH a password which is `1234`
pdftoppm -upw 1234 mypdf.pdf -f 1000000 2>&1 | grep -o '([0-9]*).$'
| grep -o '[0-9]*'
这是怎么回事?好吧,如果你指定的f
第一页比PDF中的页面大(我指定的页码1000000
对所有已知的PDF来说都太大了),它会将以下错误打印到stderr
:
给定的页面范围错误:第一页(1000000)不能在最后一页(142)之后。
因此,我将stderr
消息用2>&1
管道传输到stdout
,如这里所解释的,然后我将其管道传输到grep,以将(142).
部分与该正则表达式(([0-9]*).$
)匹配,然后我用该正则表达式再次管道传输到grep([0-9]*
),以仅找到数字,在这种情况下为142
。就是这样!
包装器功能和速度测试
这里有几个包装器函数来测试这些:
# get the total number of pages in a PDF; technique 1.
# See this ans here: https://stackoverflow.com/a/14736593/4561887
# Usage (works on ALL PDFs--whether password-protected or not!):
# num_pgs="$(getNumPgsInPdf "path/to/mypdf.pdf")"
# SUPER SLOW! Putting `time` just in front of the `strings` cmd shows it takes ~0.200 sec on a 142
# pg PDF!
getNumPgsInPdf() {
_pdf="$1"
_num_pgs="$(strings < "$_pdf" | sed -n 's|.*/Count -{0,1}([0-9]{1,}).*|1|p'
| sort -rn | head -n 1)"
echo "$_num_pgs"
}
# get the total number of pages in a PDF; technique 2.
# See my ans here: https://stackoverflow.com/a/66963293/4561887
# Usage, where `pw` is some password, if the PDF is password-protected (leave this off for PDFs
# with no password):
# num_pgs="$(getNumPgsInPdf2 "path/to/mypdf.pdf" "pw")"
# SUPER FAST! Putting `time` just in front of the `pdftoppm` cmd shows it takes ~0.020 sec OR LESS
# on a 142 pg PDF!
getNumPgsInPdf2() {
_pdf="$1"
_password="$2"
if [ -n "$_password" ]; then
_password="-upw $_password"
fi
_num_pgs="$(pdftoppm $_password "$_pdf" -f 1000000 2>&1 | grep -o '([0-9]*).$'
| grep -o '[0-9]*')"
echo "$_num_pgs"
}
用前面的time
命令测试它们表明,strings
的速度非常慢,在142 pg pdf上需要~0.200秒,而pdftoppm
的速度非常快,在同一pdf上需要~0.020秒或更短。Ocaso下面的答案中的pdfinfo
技术也非常快——与pdftoppm
技术相同。
另请参阅
- 奥卡索·普罗塔尔的这些令人敬畏的答案
- 以上这些功能将在我的
pdf2searchablepdf
项目中使用:https://github.com/ElectricRCAircraftGuy/PDF2SearchablePDF.
mupdf/mutool解决方案:
mutool info tmp.pdf | grep '^Pages' | cut -d ' ' -f 2
我刚刚挖出了一个旧脚本(在ksh中):
#!/usr/bin/env ksh
# Usage: pdfcount.sh file.pdf
#
# Optimally, this would be a mere:
# pdfinfo file.pdf | grep Pages | sed 's/[^0-9]*//'
[[ "$#" != "1" ]] && {
printf "ERROR: No file specifiedn"
exit 1
}
numpages=0
while read line; do
num=${line/*([[:print:]])+(Count )?(-)+({1,4}(d))*([[:print:]])/4}
(( num > numpages)) && numpages=$num
done < <(strings "$@" | grep "/Count")
print $numpages
如果你在macOS上,你可以查询pdf元数据,如下所示:
mdls -name kMDItemNumberOfPages -raw file.pdf
如图所示https://apple.stackexchange.com/questions/225175/get-number-of-pdf-pages-in-terminal
另一个更好地利用选项的多工具解决方案:
mutool show file.pdf Root/Pages/Count
我对Marius Hofert提示进行了一些改进,以对返回值求和。
for f in *.pdf; do pdfinfo "$f" | grep Pages | awk '{print $2}'; done | awk '{s+=$1}END{print s}'
为了建立在Marius Hofert的答案之上,此命令使用bash for循环来显示页数、显示文件名,并且将忽略文件扩展名的大小写。
for f in *.[pP][dD][fF]; do pdfinfo "$f" | grep Pages | awk '{printf $2 }'; echo " $f"; done