Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
251 lines (198 sloc) 8.13 KB
#!/bin/bash
# --------------------------------------------
# Generate a PDF document from a given list of documents
# Documents are added in final document following
# alphabetical order
#
# Setup procedure : http://bernaerts.dyndns.org/linux/74-ubuntu/338-ubuntu-generate-pdf-from-documents
#
# Depends on :
# * mimetype
# * convert [imagemagick]
# * unoconv
# * wkhtmltopdf
# * gs [ghostscript]
#
# Revision history :
# 05/07/2015, V1.0 - Creation by N. Bernaerts
# 15/08/2015, V1.1 - Force jpeg quality to 95
# 25/09/2015, V1.2 - Add configuration file
# 02/10/2015, V2.0 - Code rewrite to handle progress and notification
# 01/05/2016, V2.1 - Add HTML conversion
# 12/10/2017, V2.2 - Correct PNG conversion bug giving white page
# ---------------------------------------------------
# -------------------------------------------------------
# check tools availability
# -------------------------------------------------------
command -v mimetype >/dev/null 2>&1 || { zenity --error --text="Please install mimetype"; exit 1; }
command -v convert >/dev/null 2>&1 || { zenity --error --text="Please install convert [imagemagick]"; exit 1; }
command -v unoconv >/dev/null 2>&1 || { zenity --error --text="Please install unoconv"; exit 1; }
command -v wkhtmltopdf >/dev/null 2>&1 || { zenity --error --text="Please install wkhtmltopdf"; exit 1; }
command -v gs >/dev/null 2>&1 || { zenity --error --text="Please install gs utility [ghostscript]"; exit 1; }
# ---------------------------------------------------------
# Read and calculate parameters from configuration file
# ---------------------------------------------------------
# Configuration file : ~/.config/pdf-generate.conf
FILE_CONF="$HOME/.config/pdf-generate.conf"
# check configuration file
[ -f "$FILE_CONF" ] || { zenity --error --text="Please create and configure ${FILE_CONF}"; exit 1; }
# Load configuration file
COMPRESSION=$(cat "${FILE_CONF}" | grep "compression" | cut -d'=' -f2)
DENSITY=$(cat "${FILE_CONF}" | grep "density" | cut -d'=' -f2)
# calculate page size
PAGE_WIDTH=$((${DENSITY} * 827 / 100))
PAGE_HEIGHT=$((${DENSITY} * 1170 / 100))
# -------------------------------------------------------
# Retrieve or select input files
# -------------------------------------------------------
# set separator as carriage return
IFS=$'\n'
# loop thru arguments to load candidate files
for ARGUMENT
do
[ -f "${ARGUMENT}" ] && ARR_FILE=("${ARR_FILE[@]}" "${ARGUMENT}")
[ -d "${ARGUMENT}" ] && ARR_FILE=("${ARR_FILE[@]}" $(find "${ARGUMENT}" -maxdepth 1 -type f) )
done
# if there is no candidate files, open selection dialog
if [ ${#ARR_FILE[@]} -eq 0 ]
then
# open multiple files selection dialog box
LST_FILE=$(zenity --file --multiple --title="Select file to merge as PDF")
# generate video files array
ARR_FILE=($(echo "${LST_FILE}" | tr "|" "\n"))
fi
# -------------------------------------------------------
# loop thru selected files to check convertibility
# -------------------------------------------------------
for FILE in "${ARR_FILE[@]}"
do
# document type undefined
DOCTYPE=""
# get the file mime type (application/msword, ...)
MIMETYPE=$(mimetype -b "${FILE}")
# check if file is a image file (.jpg, .png, .tiff, ...)
CHECKTYPE=$(echo "${MIMETYPE}" | grep "image/")
[ "${CHECKTYPE}" != "" ] && DOCTYPE="image"
# check if file is a libreoffice file (.odt, .ods, ...)
CHECKTYPE=$(echo "${MIMETYPE}" | grep ".opendocument.")
[ "${CHECKTYPE}" != "" ] && DOCTYPE="libreoffice"
# check if file is a microsoft file 2007+ file (.docx, .xlsx, .pptx, ...)
CHECKTYPE=$(echo "${MIMETYPE}" | grep "vnd.openxmlformats-officedocument.")
[ "${CHECKTYPE}" != "" ] && DOCTYPE="ms-office"
# check some specific document types
case $MIMETYPE in
# ms-office document (.doc, .xls, .ppt, ...)
"application/msword" | "application/vnd.ms-word" | "application/vnd.oasis.opendocument.text" | \
"application/vnd.ms-excel" | "application/vnd.ms-powerpoint" )
DOCTYPE="ms-office"
;;
# PDF document (.pdf)
"application/pdf" | "application/x-pdf" | "application/x-bzpdf" | "application/x-gzpdf" )
DOCTYPE="pdf"
;;
# plain text file (.txt)
"text/plain" | "application/x-shellscript" )
DOCTYPE="text"
;;
# plain text file (.txt)
"text/html" )
DOCTYPE="html"
;;
* )
;;
esac
# if document type is compatible, add current file as candidate
[ "${DOCTYPE}" != "" ] && ARR_CANDIDATE=("${ARR_CANDIDATE[@]}" "${FILE}|${DOCTYPE}")
done
# -------------------------------------------------------
# Confirmation dialog box
# -------------------------------------------------------
# calculate number of files to convert
NBR_FILE=${#ARR_FILE[@]}
NBR_CANDIDATE=${#ARR_CANDIDATE[@]}
# if some candidate file exist, order them and display confirmation dialog
if [ ${NBR_CANDIDATE} -gt 0 ]
then
# order generated PDF files in alphabetical order
ARR_CANDIDATE=($(sort <<<"${ARR_CANDIDATE[*]}"))
# generate final file name
FILE=$(echo "${ARR_CANDIDATE[0]}" | cut -d'|' -f1)
FILE_FINAL="$(echo "${FILE}" | sed 's/^\(.*\)\..*$/\1/')-merged.pdf"
# display confirmation dialog box
RESULT=$(zenity --question --title="Merge to PDF" --text="${NBR_CANDIDATE} file(s) out of ${NBR_FILE} will be merged to a single PDF file (${DENSITY} DPI)\n\nDo you want to generate ${FILE_FINAL} ?" )
ACTION=$?
# else display error dialog
else
# display confirmation dialog box
RESULT=$(zenity --error --title="Merge to PDF" --text="There is no file compatible with PDF format." )
ACTION=""
fi
# if action canceled or error, exit
[ "${ACTION}" != "0" ] && exit 1
(
# -------------------------------------------------------
# loop thru candidate files to convert them to PDF
# -------------------------------------------------------
for CANDIDATE in "${ARR_CANDIDATE[@]}"
do
# retrieve document type and filename
FILE=$(echo "${CANDIDATE}" | cut -d'|' -f1)
DOCTYPE=$(echo "${CANDIDATE}" | cut -d'|' -f2)
# progress display
echo "# Conversion of ${FILE}"
# get file name without extension & generate resulting PDF file name
FILE_BASE="$(echo "${FILE}" | sed 's/^\(.*\)\..*$/\1/')"
FILE_PDF="${FILE_BASE}.pdf"
# convert file according to its type
case $DOCTYPE in
# PDF files
"pdf" )
ARR_PDF=("${ARR_PDF[@]}" "${FILE}")
;;
# image files
"image" )
convert "${FILE}" -compress jpeg -quality ${COMPRESSION} -resize ${PAGE_WIDTH}x${PAGE_HEIGHT} -extent ${PAGE_WIDTH}x${PAGE_HEIGHT} -units PixelsPerInch -density ${DENSITY}x${DENSITY} "${FILE_PDF}"
ARR_TMP=("${ARR_TMP[@]}" "${FILE_PDF}")
ARR_PDF=("${ARR_PDF[@]}" "${FILE_PDF}")
;;
# office files
"libreoffice" | "ms-office" | "text" )
unoconv -f pdf -o "${FILE_PDF}" "${FILE}"
ARR_TMP=("${ARR_TMP[@]}" "${FILE_PDF}")
ARR_PDF=("${ARR_PDF[@]}" "${FILE_PDF}")
;;
# html files
"html" )
wkhtmltopdf "${FILE}" "${FILE_PDF}"
ARR_TMP=("${ARR_TMP[@]}" "${FILE_PDF}")
ARR_PDF=("${ARR_PDF[@]}" "${FILE_PDF}")
;;
# other formats, not handled
* )
;;
esac
done
# -------------------------------------------------------
# Final merge
# -------------------------------------------------------
if [ ${#ARR_PDF[@]} -gt 0 ]
then
# progress display
echo "# Final assembly of ${FILE_FINAL}"
# generate resulting PDF
gs -q -dNOPAUSE -dBATCH -dSAFER -sPAPERSIZE=a4 -dPDFFitPage -dCompatibilityLevel=1.4 -sDEVICE=pdfwrite -sOutputFile="${FILE_FINAL}" ${ARR_PDF[@]}
fi
# -------------------------------------------------------
# Temporary files clean-up
# -------------------------------------------------------
# loop to remove temporary files
for TMP_FILE in "${ARR_TMP[@]}"
do
rm "${TMP_FILE}"
done
) | zenity --width=500 --height=25 --progress --pulsate --auto-close --title "Merge to PDF"
# -------------------------------------------------------
# End of job notification
# -------------------------------------------------------
[ ${#ARR_CANDIDATE[@]} -gt 0 ] && zenity --notification --window-icon="evince" --text="${FILE_FINAL} generated." \
|| zenity --notification --window-icon="error" --text="Document type was not compatible for PDF generation."