#bash #pdf #imagemagick #tiff #imagemagick-convert
#bash #PDF #imagemagick #tiff #imagemagick-конвертировать
Вопрос:
У меня следующий сценарий, и я не очень хороший программист (и я плохо знаю bash). У меня даже нет базового рабочего скрипта bash для совместного использования, поэтому буду признателен за любую помощь.
У меня есть общий файловый ресурс, который содержит tiff (тысячи) системы управления документами. Цель состоит в том, чтобы преобразовать и объединить несколько файлов tiff в один файл pdf (предпочтительно формат PDF / A 1a).
Формат каталога:
/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 независимо от того, что это за следующий файл.
Любая помощь будет очень признательна.
РЕДАКТИРОВАТЬ — оба ответа ниже работают. Второй ответ сработал, однако я допустил ошибку, не поняв, что набор данных, с которым я тестировал, отличался от моего сценария выше.
Ответ №1:
Итак, сохраните следующий скрипт в вашем каталоге login ($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
или, предпочтительно, если у вас установлен GNU Parallel:
~/TIFF2PDF | parallel
Сценарий говорит… «Создайте список всех файлов, имена которых заканчиваются на цифру, и отправьте этот список awk
. В awk
, используйте точку в качестве разделителя между полями, поэтому, если файл вызывается 00011.0002
, тогда $0
будет 00011.0002
, $1
будет 00011
и $2
будет 0002
. Теперь, если имя файла заканчивается на 0001
, выведите накопленную команду и добавьте выходное имя файла. Затем сохраните префикс имени файла с PDF
расширением в качестве выходного имени следующего PDF-файла и начните создавать следующую команду ImageMagick convert
. В последующих строках (которые не заканчиваются на 0001
) добавьте имя файла в список имен файлов для включения в PDF
. В конце выведите все накопленные команды и добавьте выходное имя файла. «
Что касается уродливого черного блока в нижней части вашего изображения, это происходит потому, что там есть несколько крошечных белых пятнышек, которые мешают ImageMagick удалить черную область. Я обвел их красным кружком:
Если вы немного размываете изображение (чтобы рассеять пятна), а затем получаете размер рамки обрезки, вы можете применить это к исходному, не размытому изображению, например:
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 символов, поэтому у вас могут возникнуть проблемы, если в одном каталоге более 26 000 файлов. Если это так, просто измените:
ls *[0-9] | awk ...
Для
ls | grep "d$" | awk ...
Комментарии:
1. Это успешно создает результат, соответствующий вашему образцу вывода.
2. Кажется, это помогло, но внизу есть черная окантовка, от которой я не могу избавиться. Я изменил раздел cmd= ‘convert’ следующим образом:
cmd="convert " $0 " -fuzz 1% -trim repage ";next}
. Похоже, это ничего не меняет. Я очистил один из созданных документов (зеленая рамка представляет отредактированное наложение): dropbox.com/s/bxhnrfro69zwzez/00000023.pdf?dl=03. Это другая проблема — этот вопрос касается объединения последовательно пронумерованных документов в один PDF-файл. Могу ли я предложить вам задать новый вопрос, предоставив один из ваших искаженных сканов (предположительно?). — желательно, по крайней мере, с каким-нибудь образцом текста и вопросом, как избавиться от черного?
4. понял. Я отмечу ваш ответ как Ответ. Большое вам спасибо за помощь.
5. @MarkSetchell, есть несколько потенциальных проблем с вашим решением. Наихудший вариант — использовать глобализацию в
ls
команде в папке с потенциально тысячами файлов.
Ответ №2:
Следующая команда преобразует все /Document Management Root
дерево (при условии, что это фактический абсолютный путь), правильно обрабатывая все вложенные папки, даже с именами, включающими пробелы, и правильно пропуская все другие файлы, не соответствующие шаблону 000000.000
именования:
find '/Document Management Root' -type f -regextype sed -regex '.*/[0-9]{6}.001
Чтобы сделать сухой прогон, просто снимите | bash
его в конце.
Обновлено в соответствии с 00000000.000
шаблоном (и разделено на несколько строк для наглядности):
find '/Document Management Root' -type f -regextype sed -regex '.*/[0-9]{8}.001
Комментарии:
1. Это возвращает только приглашение и не вносит никаких изменений в файлы в корневом каталоге Document Management.
2. вы пробовали использовать
echo
вместоconvert
? также сделайтеecho $BASH_VERSION
3. Попробовал 'echo' вместо 'convert', и он вернул подсказку.
4. echo $BASH_VERSION отображает 4.3.46(1)-release.
5. ваш
bash
достаточно недавний, чтобы эта-exec
часть не была проблемой. так что запуститеfind
without the-exec
part, чтобы посмотреть, найдет ли он что-нибудь
-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 "%sd.d" "$d" $k $i); [[ -f "$l" ]] || break; c[$i]="$l"; done; echo -n "convert"; printf " %q" "${c[@]}" "$d$n.pdf"; echo' ; | bash
Чтобы сделать сухой прогон, просто снимите | bash
его в конце.
Обновлено в соответствии с 00000000.000
шаблоном (и разделено на несколько строк для наглядности):
Комментарии:
1. Это возвращает только приглашение и не вносит никаких изменений в файлы в корневом каталоге Document Management.
2. вы пробовали использовать
echo
вместоconvert
? также сделайтеecho $BASH_VERSION
3. Попробовал 'echo' вместо 'convert', и он вернул подсказку.
4. echo $BASH_VERSION отображает 4.3.46(1)-release.
5. ваш
bash
достаточно недавний, чтобы эта-exec
часть не была проблемой. так что запуститеfind
without the-exec
part, чтобы посмотреть, найдет ли он что-нибудь
-exec bash -c '
pages[1]="{}"
p1num="10#${pages[1]: -12:8}"
for i in {2..999}; do
nextpage=$(printf "%sd.d" "${pages[1]:0: -12}" $((p1num i-1)) $i)
[[ -f "$nextpage" ]] || break
pages[i]="$nextpage"
done
echo -n "convert"
printf " %q" "${pages[@]}" "${pages[1]:0: -3}pdf"
echo
' ; | bash
Комментарии:
1. Это возвращает только приглашение и не вносит никаких изменений в файлы в корневом каталоге Document Management.
2. вы пробовали использовать
echo
вместоconvert
? также сделайтеecho $BASH_VERSION
3. Попробовал ‘echo’ вместо ‘convert’, и он вернул подсказку.
4. echo $BASH_VERSION отображает 4.3.46(1)-release.
5. ваш
bash
достаточно недавний, чтобы эта-exec
часть не была проблемой. так что запуститеfind
without the-exec
part, чтобы посмотреть, найдет ли он что-нибудь
—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 «%sd.d» «$d» $k $i); [[ -f «$l» ]] || break; c[$i]=»$l»; done; echo -n «convert»; printf » %q» «${c[@]}» «$d$n.pdf»; echo’ ; | bash
Чтобы сделать сухой прогон, просто снимите | bash
его в конце.
Обновлено в соответствии с 00000000.000
шаблоном (и разделено на несколько строк для наглядности):
Комментарии:
1. Это возвращает только приглашение и не вносит никаких изменений в файлы в корневом каталоге Document Management.
2. вы пробовали использовать
echo
вместоconvert
? также сделайтеecho $BASH_VERSION
3. Попробовал ‘echo’ вместо ‘convert’, и он вернул подсказку.
4. echo $BASH_VERSION отображает 4.3.46(1)-release.
5. ваш
bash
достаточно недавний, чтобы эта-exec
часть не была проблемой. так что запуститеfind
without the-exec
part, чтобы посмотреть, найдет ли он что-нибудь