Замечательный файловый менеджер 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 для копирования сценариев в каталоги пользователя.
Комментарии (5)
Writer
22.09.2022 12:17+1Если речь о Dolphin и KDE, то совершенно непонятно, зачем вам Zenity в первом примере, надо было везде уведомления через kdialog выводить. Ну или использовать Qarma.
Тема сервисных меню в KDE не раскрыта - а это интереснейший момент, про который мало кто пишет.
Куски скриптов без заголовков, без контекста, с обрывочным комментарием - ну такое...
Так себе статья, уж извините.
VlaSard Автор
22.09.2022 14:13kdialog лучше работает с диалоговыми окнами выбора. zenity лучше выглядит при выводе сообщений. Если память не изменяет то выбор делался из возможностей для той или иной задачи и оформления окон. Что касается "кусков скриптов" в статью не планировалось добавлять тексты в полном объеме. Для просмотра всего скрипта приведена ссылка на github. Реп публичный. Здесь показал как можно работать с pdf не устанавливая специализированного ПО.
По поводу "так себе статья" кому то нравится кому то нет.
Qarma это клон Zenity. Приводить его против Zenity такой себе вариант.
economist75
Хорошие скрипты. Для любителей файлового менеджера Nautilus (он, вдобавок, умеет отображать мета-свойства файла в отдельных столбцах: автора, комментарий, ключевые слова, название документа итд) - так вот для Nautilus можно писать подобные PDF-скрипты на Python, с интеграцией в меню. Возможно их уже написано много, но написать свой под свой МФУ/документооборот/бизнес-процесс - не только зачетно, но и порой остро необходимо. В экосистеме Python много свободных PDF-либ для любых манипуляций:
segno - лучшая вставка QR и DataMatrix-кодов в готовый PDF
PyPDF2 - простая нумерация страниц и др. операции
pypdftk - разрезка/склейка/поворот/закладки/метаинформация
PyMuPDF - вообще почти все мыслимые манипуляции
VlaSard Автор
Есть написанные и на Python с использованием pikepdf. Но смешивать shell и Python как-то не хочется.
VlaSard Автор
Пример сценария на Python: https://github.com/VlaSard/my-script-py/blob/master/pypdf
и desktop файл к нему: https://github.com/VlaSard/my-script-py/blob/master/pypdf.desktop