Замечательный файловый менеджер Dolphin всем хорош. И две панели, и разнообразные контекстные меню ускоряющие обработку всевозможных команд и заданий. Но что делать если нужно простенько и быстро собрать несколько одностраничных pdf-файлов? Не устанавливать же из-за этого тяжеловесное ПО, которым в последствии пользоваться крайне редко. Конечно же нет. Просто расширим возможности нашего менеджера, добавив пару пунктов в контекстное меню. Тем более, что сделать это совсем не сложно. Но сначало нужно написать пару сценариев для этой самой обработки pdf-файлов. И так, приступим.
Работаем с pdf-файлами
Для обработки файлов будем использовать консольную программу pdftk. Поскольку сценарий будет встраиваться в контекстное меню, для отображения информации об ошибках, ходе выполнения будем использовать утилиту zenity. Также нам понадобятся всплывающие сообщения, за них будет отвечать notify-send.
pdfmark - объединение pdf-файлов и добавление закладок
Раз скрипту передаются какие-то аргументы, то нужно проверять что и сколько было передано через командную строку. А раз аргументов не так много то и проверку пишем в две строчки. Первой проверяем вызов справки по ключам -h и --help. Второй строчкой проверим только количество переданных файлов, один файл нет смысла обрабатывать.
Далее создаем временную директорию и уже в ней создаем файл закладок для будущего объединеного pdf-файла. Добавим заголовок документа по имени директории из которой объединяем файла. В качестве имени автора документа используем имя пользователя. Добавляем закладки по именам файлов в файл закладок. Производим объединение, добавляем закладки, проверяем успешность операции по наличию итогового файла и выводим соответствующие сообщения. Перед выходом удаляем временную директорию.
pdfmark: закладки и объединение
{ NumberPage=1 echo "InfoBegin" echo "InfoKey: Title" echo "InfoValue: ${WorkDir}" echo "InfoBegin" echo "InfoKey: Author" echo "InfoValue: ${USER^}" echo "NumberOfPages: ${#FileList[@]}" for BookMark in "${MarkList[@]}"; do echo "BookmarkBegin" echo "BookmarkTitle: ${BookMark}" echo "BookmarkLevel: 1" echo "BookmarkPageNumber: ${NumberPage}" ((NumberPage += 1)) done } >>"${TmpDir}"/file.info # объединить выбранные документы и добавить закладки (pdftk "${@}" cat output "${TmpDir}"/"${WorkDir}".pdf && pdftk "${TmpDir}"/"${WorkDir}".pdf update_info "${TmpDir}"/file.info output "${WorkDir}.pdf") | zenity --progress --title="${msg_title}" --text="${msg_progress}" --pulsate --width=500 --no-cancel --auto-close --auto-kill
pdf_service_menu - меню для обработки pdf файлов
Второй сценарий будет выполнять больше операций с pdf файлами. Список доступных операций:
burst - позволяет разобрать весь документ на станицы;
extract - извлекает указанные страницы из документа;
remove - удаляет диапазон страниц из документа;
cat - объединяет документы;
add - добавляет выбранные документы, в порядке их выбора;
stamp - ставит штамп на страницы документа;
pdf2jpg - позволяет преобразовать страницы документа в jpg;
info - отображает информацию о документе;
Здесь в качестве графических диалогов используем kdialog. По сути тот же zenity но ближе к kde. И подойдет намного лучше по оформлению к Dolphin.
Простые функции такие как burst, extract и подобные описывать нет смысла. Там все просто и понятно.
Интерес представляет функция remove которая удаляет диапазон страниц из документа. pdfkt не п��ддерживает удаление страниц. Но зато может извлекать страницы как по одной так и диапазон страниц. Этот трюк и используем для удаления диапазона страниц.
В первую очередь нужно определить диапазон страниц. Запрашиваем у пользователя через kdialog границы диапазона. И определяем номер последней страницы в документе. Он нужен чтобы не выйти за границы документа.
pdf_service_menu: kdialog - диапазоны страниц
msg_remove_title="Удалить страницы..." msg_remove_range="Диапазон страниц для удаления из документа\n\"${filename}\"\n\nИнструкция:\n\nКлючевое слово \"end\" может использоваться, чтобы сослаться на заключительную\nстраницу документа, вместо номера страницы. Сошлитесь на одну страницу, опуская\nномер конечной страницы.\n\nПримеры:\n\n2 - удалить страницу 2;\n3-45 - удалить страницы с 3 по 45;\n5-end - удалить страницы с 5 по последнюю.\n\nВведите диапазон страниц для удаления:" range="$(kdialog --icon viewpdf --title "${msg_remove_title}" --inputbox "${msg_remove_range}" "2-end")" || return 1 . . . totalpages="$(pdftk "${@}" dump_data | grep "NumberOfPages" | cut -d" " -f 2-)"
Затем проверяем начальный и конечный диапазоны страниц. Нам необходимо убедиться что не выходим за границы документа.
pdf_service_menu: диапазоны страниц
first="${range%-*}" if [ "${first}" = "end" ]; then first="${totalpages}" else first="${first//[^[0-9]]/}" if [ -z "${first}" ]; then first=1 else if [ "${first}" -eq 0 ]; then first=1 elif [ "${first}" -gt "${totalpages}" ]; then first="${totalpages}" fi fi fi . . . last="${range#*-}" if [ "${last}" = "end" ]; then last="${totalpages}" else last="${last//[^[0-9]]/}" if [ -z "${last}" ]; then last="${totalpages}" elif [ "${last}" -lt "${first}" ]; then last="${first}" elif [ "${last}" -gt "${totalpages}" ]; then last="${totalpages}" fi fi
После всех подготовительных операций определяем границы диапазнов для извлечения страниц.
pdf_service_menu: диапазоны страниц для извлечения
# определяем диапазон страниц range1 if [ "${first}" -eq 1 ]; then range1='' elif [ "${first}" -eq 2 ]; then range1="1" else range1="1-$((first - 1))" fi # определяем диапазон страниц range2 if [ "${last}" -eq "${totalpages}" ]; then range2='' elif [ "${last}" -eq "$((totalpages - 1))" ]; then range2="${totalpages}" else range2="$((last + 1))-${totalpages}" fi
Далее проверяем что не удаляем все страницы из документа, указываем куда сохранить итоговый файл. И выполняем извлечение страниц в найденых диапазонах.
Подключаем сценарии в контекстное меню
Сценарии готовы осталось подключить их в контекстное меню Dolphin. Пишем простенький desktop файл в котором расписываем наши функции и бросаем его в директорию ServiceMenus.
Заключение
Все сценарии и функции писались исключительно из задач которые чаще всего приходилось решать. stamp был добавлен позже в экспериментальных целях так и остался. info - тоже особой функциональности не придает. А все остальные функции используются достаточно часто и востребованы. Перед использованием данных сценариев нужно убедиться что установлены все пакеты используемые в сценариях. pdftk к примеру должен устанавливаться отдельно.
Все сценарии и desktop файл доступны на github. Там же находится простенький скрипт install.sh для копирования сценариев в каталоги пользователя.
