Bash ImageMagick使用顺序文件后缀将TIFF转换为pdf

Bash ImageMagick使用顺序文件后缀将TIFF转换为pdf,bash,pdf,imagemagick,tiff,imagemagick-convert,Bash,Pdf,Imagemagick,Tiff,Imagemagick Convert,我有下面的场景,我不是一个程序员(我也不太了解bash)。我甚至没有一个基本的bash脚本可以共享,所以任何帮助都将不胜感激 我有一个文件共享,其中包含文档管理系统的TIFF(数千)。目标是将多个文件TIFF转换为单个文件PDF(最好是PDF/A格式),并将其组合 目录格式: /Document Management Root # This is root directory ./2009/ # each subdirectory repres

我有下面的场景,我不是一个程序员(我也不太了解bash)。我甚至没有一个基本的bash脚本可以共享,所以任何帮助都将不胜感激

我有一个文件共享,其中包含文档管理系统的TIFF(数千)。目标是将多个文件TIFF转换为单个文件PDF(最好是PDF/A格式),并将其组合

目录格式:

/Document Management Root     # This is root directory
 ./2009/                      # each subdirectory represents a year
 ./2010/
 ./2011/
 ....
 ./2016/
 ./2016/000009.001            
 ./2016/000010.001
              # files are stored flat - just thousands of files per year directory
文档管理系统使用顺序编号文件名和顺序文件后缀存储TIFF:

000009.001
000010.001
000011.002
000012.003
000013.001
其中,文档的每一页都由后缀表示。创建新的、不相关的文档时,后缀将重新启动。在上面的示例中,
000009.001
是一个单页tiff。文件
000010.001
000011.002
000012.003
属于同一文档(即,所有页面都是相关的)。文件
000013.001
表示一个新文档

我需要为多页文档的第一个文件保留文件名,以便文件名可以与文档管理系统元数据数据库交叉引用

我想到的伪代码是:

for each file in {tiff directory}
    while file extension is "001"
      convert file to pdf and place new pdf file in {pdf directory}
    else 
      convert multiple files to pdf and place new pd file in {pdf  directory}
但这似乎会产生转换所有001个文件的副作用,而不管下一个文件是什么

非常感谢您的帮助


编辑-下面的两个答案都有效。第二个答案有效,但我的错误在于没有意识到我测试的数据集与上面的场景不同。

因此,将以下脚本保存在您的登录($HOME)目录中,作为
TIFF2PDF

#!/bin/bash
ls *[0-9] | awk -F'.' '
   /001$/ { if(NR>1)print cmd,outfile; outfile=$1 ".pdf"; cmd="convert " $0;next}
          { cmd=cmd " " $0}
   END    { print cmd,outfile}'
并通过进入终端并运行以下命令使其可执行(只需一次):

chmod +x TIFF2PDF    
然后将任何一年的一些文档复制到一个临时目录中进行尝试。。。然后转到目录并运行:

~/TIFF2PDF
样本输出

convert 000009.001 000009.pdf
convert 000010.001 000011.002 000012.003 000010.pdf
convert 000013.001 000013.pdf
如果这看起来是正确的,您可以像这样执行这些命令:

~/TIFF2PDF | bash
trimbox=$(convert original.tif -blur x2 -bordercolor black -border 1 -fuzz 50% -format %@ info:)
convert original.tif -crop $trimbox result.tif
或者,如果您安装了GNU Parallel,最好是:

~/TIFF2PDF | parallel
剧本上说。。。“生成名称以数字结尾的所有文件的列表,并将该列表发送到
awk
。在
awk
中,使用点作为字段之间的分隔符,因此如果文件名为
00011.0002
,则
$0
将为
00011.0002
$1
将为
00011
$2
将为
00。”02
。现在,如果文件名以
0001
结尾,则打印累积的命令并附加输出文件名。然后将扩展名为
PDF
的文件名前缀保存为下一个PDF的输出文件名,并开始构建下一个ImageMagick转换命令。在后续行中(不以
0001
结尾),将文件名添加到要包含在
PDF
中的文件名列表中。最后,输出所有累积命令并附加输出文件名。”


至于图像底部丑陋的黑色块,之所以会出现这种情况,是因为其中有一些微小的白色斑点阻止ImageMagick去除黑色区域。我用红色圈出了它们:

如果稍微模糊图片(使斑点漫射),然后获得修剪框的大小,则可以将其应用于原始的未模糊图像,如下所示:

~/TIFF2PDF | bash
trimbox=$(convert original.tif -blur x2 -bordercolor black -border 1 -fuzz 50% -format %@ info:)
convert original.tif -crop $trimbox result.tif

我建议您先复制所有图像,然后再运行PDF转换。由于您希望保存TIFF文件,但扩展名为
0001
0002
,因此需要告诉ImageMagick修剪并强制输出文件类型为TIF:

original=XYZ.001
trimbox=$(convert $original -blur x2 -bordercolor black -border 1 -fuzz 50% -format %@ info:)
convert $original -crop $trimbox TIF:$original

正如@AlexP.提到的,如果存在大量文件,则全局绑定可能会出现问题。在OSX上,ARG_MAX非常高(262144),并且您的文件名约为10个字符,因此如果一个目录中的文件超过26000个,则可能会遇到问题。如果是这种情况,只需更改:

ls *[0-9] | awk ...


以下命令将转换整个
/Document Management Root
树(假设它是实际的绝对路径),正确处理所有子文件夹(即使名称包含空格字符),并正确跳过与
000000000
命名模式不匹配的所有其他文件:

find '/Document Management Root' -type f -regextype sed -regex '.*/[0-9]\{6\}.001$' -exec bash -c 'p="{}"; d="${p:0: -10}"; n=${p: -10:6}; m=10#$n; c[1]="$d$n.001"; for i in {2..999}; do k=$((m+i-1)); l=$(printf "%s%06d.%03d" "$d" $k $i); [[ -f "$l" ]] || break; c[$i]="$l"; done; echo -n "convert"; printf " %q" "${c[@]}" "$d$n.pdf"; echo' \; | bash
要进行试运行,只需最后删除
|bash

更新以匹配
00000000.000
模式(为了清晰起见,将其拆分为多行):


这成功地生成了与示例输出匹配的输出。这似乎已经完成,但底部有一个黑色边框,我无法消除。我修改了cmd='convert'部分,如下所示:
cmd=“convert”$0”-fuzz 1%-trim+repage”;next}
。这似乎没有什么区别。我对创建的一个文档进行了清理(绿色边框表示已编辑的覆盖):这是另一个问题-这个问题是关于将按顺序编号的文档合并到单个PDF中。我可以建议您问一个新问题,提供一个倾斜扫描(大概是吧?)-最好是至少有一些示例文本,并询问如何去除黑色?明白了。我会将您的回答标记为答案。非常感谢您的帮助。@MarkSetchell,您的解决方案存在两个潜在问题。最糟糕的是在可能包含数千个文件的文件夹中使用
ls
命令中的globbing。This仅返回提示,不对文档管理根目录中的文件进行任何更改。您是否尝试过使用
echo
而不是
convert
?也尝试了
echo$BASH_VERSION
而不是'convert',并返回提示。echo$BASH_VERSION显示4.3.46(1)-release.your
bash
足够新,因此
-exec
部分不会成为问题。因此,在不使用
-exec
部分的情况下运行
find
,以查看是否找到任何内容