Contenu | Rechercher | Menus

Annonce

DVD, clés USB et t-shirts Ubuntu-fr disponibles sur la boutique En Vente Libre

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 23/07/2019, à 17:03

Arbiel

Remise en ordre des pages d'un document papier recto-verso

Bonjour

Je vous propose un script pour remettre en ordre les pages d'un document recto-verso sans avoir à manipuler le paquet de feuilles.

J'en ai introduit l'appel dans le lanceur

remi@remi-Vostro-3550:~$ cat '/home/remi/Documents/programmation/lanceurs/simple-scan.desktop' 
[Desktop Entry]
Name=Simple Scan
Comment=Scan Documents
Exec=simple-scan
Icon=scanner
Terminal=false
Type=Application
StartupNotify=true
Categories=GNOME;GTK;Graphics;Scanning;
X-GNOME-Gettext-Domain=simple-scan

Actions=Cl

[Desktop Action Cl]
Name=Ordonnancement de photocopie recto/verso
Exec=pdf ordonne
OnlyShowIn=Unity;
remi@remi-Vostro-3550:~$ 

Attention : le snap de pdftk ne fonctionne plus. J'indique ici, en attendant mieux, comment j'ai résolu le problème.

Ci-dessous le script en question.

#!/bin/bash
# mise à jour le 29 novembre 2017 à 16:00:00
# Les fonctions de ce script sont appelées par une ligne de commande telle que "pdf <fonction> <paramètres>"
# dans laquelle fonction peut être
# lots
# tranche
# ordonne
##################################################################
#
# Découpage d'un fichier pdf selon les numéros de page donnés en paramètres
#
####################################################################
function lots () {
	local pdf="${1}" ; # fichier pdf à découper en lots dont la première page de chacun est
# définie par la suite des paramètres au dela du nom du fichier
	( [ -z "${pdf}" ] || ! [ -s "${pdf}" ] ) && return 1 ;
	base="$(basename "${pdf}")";
	npd=$(pdftk "${pdf}" dump_data 2>/dev/null | grep NumberOfPages  | grep  -o -E "[[:digit:]]+$");
	shift 1;
	pp="${1}";
	i=0
	while shift 1; do
		ppp="${1}";
		[ -z "${ppp}" ] && dp=${npd} || dp=$((ppp - 1));
		[ $((dp)) -gt $((npd)) ] && dp=${npd};
		pdftk A="${pdf}" cat A${pp}-${dp} output /tmp/$((++i))-"(pages "${pp}" à "${dp}")"-${base};
		[ $((dp)) -ge $((npd)) ] && break 1;
		pp="${ppp}";
		done;
	return 0 ;
	}
##########################################################
#
# Découpage d'un fichier pdf en tranches de taille identique, sauf éventuellement la dernière
#
##########################################################
function tranche () {
	local pdf="${1}" ; # fichier pdf à découper en tranches
	local npt="${2}" ; # nombre de pages par tranche
	( [ -z "${pdf}" ] || ! [ -s "${pdf}" ] ) && return 1 ;
	base="$(basename "${pdf}")";
	i=0;
	npd=$(pdftk "${pdf}" dump_data 2>/dev/null | grep NumberOfPages  | grep  -o -E "[[:digit:]]+$");
	while [ $((npt * i++)) -lt $((npd)) ]; do
		pp=$((npt * (i - 1) + 1));
		dp=$((pp + npt - 1));
		[ $((dp)) -gt $((npd)) ] && dp=${npd};
		echo "pages ${pp} à ${dp} dans /tmp/${i}-${base}";
		pdftk A="${pdf}" cat A${pp}-${dp} output /tmp/${i}-${base};
		done;
	return 0 ;
	}
function Initialisations () {
# rvc (rectos versos concaténés) : les versos viennent à la suite des rectos dans un fichier unique
# sinon les rectos sont dans un fichier et les versos dans un autre fichier ; aucun test n'est effectué sur le nombre de pages 
# de ces deux fichiers
	rvc=true
# pri (premier recto inclus) : le recto de la première feuille doit être inclus dans le document final
# sinon, la première page du document final est le verso de la première feuille
	pri=true
# rpr (réorientation pages rectos) les pages rectos sont à l'endroit et ne doivent par être retournées de 180°
	rpr=
# dvi (dernier verso inclus) : le verso de la dernière feuille doit être inclus dans le document final
	dvi=true
# rpv (réorientation pages versos) les pages versos sont à l'endroit et ne doivent par être retournées de 180°
	rpv=
# opt (options) le script est exécuté à partir d'une ligne de commande, par exemple à partir d'un lanceur par "glisser/déposer" 
# du fichier à traiter, ceci pour permettre l'exécution sans interface graphique (le binaire de yad n'est pas dans le dépot)
	opt=false
	return 0
}

function LesOptions () {
# sera intégré dans la prochaine version, si elle voit le jour
	:
}

function LesRessources () {
############################################################
# vérification présence des ressources nécessaires
###########################################################
	which zenity > /dev/null && zenity=true || zenity=false ;
	which pdftk > /dev/null && pdftk=true || pdftk=false ;
	which yad > /dev/null && yad=true && zenity=false || yad=false ;
	! ${yad} && ${pdftk} && Msg_Err e=130 ;
	${yad} && ! ${pdftk} && Msg_Err e=131 ;
	! ${yad} && ! ${pdftk} && Msg_Err e=132 ;
}

function Msg_Err () {
# le premier paramètre est une instruction «e=num», ce qui facilite la recherche de l'instruction
# qui décèle une erreur dont on connait le numéro
	local e
	
	function yad_err_msg () {
		local msg="${1}"
		yad --text-info --title="${titre}" --button="Erreur ${e}:1" \
		--text-align=center \
		--width=500 \
		--text="${msg}" --sticky --center
	}

	function zen_err_msg () {
		local msg="${1}"
		zenity --error --text="${msg}" --title="${titre}" --width=350 --height=60 --no-wrap ;
	}
	
	function echo_err_msg () {
		local msg="${1}" ;
		echo "${titre}" 1>/dev/stderr ;
		echo "${msg}" 1>/dev/stderr ;
	}
	
	eval ${1} ;
	case "${e}" in
		0) msg="Le fichier\n\"${2}\"\na été correctement créé." ;;
		128) msg="Vous n'avez spécifié aucun fichier à traiter." ;;
		129) msg="Le fichier \"${2}\" n'est pas un fichier pdf ou ne peut pas être lu." ;
				msg="${msg}\nPdftk a indiqué\n${3}" ;;
		130) msg="Yad - Yet another display https://sourceforge.net/projects/yad-dialog/ - est indispensable pour utiliser ce script." ;;
		131) msg="Pdftk - Pdf tool kit - est indispensable pour utiliser ce script." ;;
		132) msg="Yad et Pdftk sont indispensables pour utiliser ce script." ;;
		133) msg="Le traitement a échoué.\nPdftk a indiqué\n${2}" ;;
		esac ;
	titre="Ordonnancement de photocopie : erreur n° ${e}" ;
	[[ $((${e})) -gt 127 ]] && msg="${msg}\n Arrêt immédiat."
	${yad} && yad_err_msg "${msg}" ;
	! ${yad} && ${zenity} && zen_err_msg "${msg}" ;
	! ${yad} && ! ${zenity} && echo_err_msg "${msg}" ;
    [[ $((${e})) -lt 127 ]] && return $((${e})) || exit $((${e}-127)) ;
}

function TestPdf () {
	local pdf="${1}" ;
		pdftk "${pdf}" dump_data 1> /tmp/pdftk.txt 2>/tmp/pdftk.err ;
		[[ $((${?})) -ne 0 ]] && Msg_Err e=129 "${pdf}" "$(cat /tmp/pdftk.err)" ;
}

function NbPagesPdf () {
	local pdf="${1}"
		pdftk "${pdf}" dump_data 2>/tmp/pdftk.err | grep NumberOfPages  | grep  -o -E "[[:digit:]]+$" ;
}

function Ordonnance_pri () {
#####################################################################################
#
#   Cette fonction est appelée lorsque le Premier Recto est Inclus [pri] dans le document final (situation la plus fréquente)
#
######################################################################################
# la variable dpe (dernière page exclue) vaut 1 si le verso de la dernière feuille du paquet doit être écarté du document final
# le document final contient alors un nombre impair de pages ; cependant, dpe ne doit pas être utilisée si la dernière feuille du paquet
# a été retirée avant de photocopier les versos

	local impaires="${1}" paires="${2}" toutes="${1}"
	if ${rvc} ; then
		np=$(NbPagesPdf "${toutes}") ;
		di=$(((${np}+1)/2)) ;
		dp=$((${di}+1+${dpe})) ;
	else
		di=$(NbPagesPdf "${impaires}") ;
		dp=$((1+${dpe})) ;
	fi
	pdftk A="${impaires}" B="${paires}" shuffle A1-${di}${rpr} Bend-${dp}${rpv} output ${trv} keep_first_id 2>/tmp/pdftk.err ;
	[[ $((${?})) -ne 0 ]] && Msg_Err e=133 "$(cat /tmp/pdftk.err)" ;

}

function Ordonnance_pre () {
#####################################################################################
#
#   Cette fonction est appelée lorsque le Premier Recto est Exclu [pre] du document final (situation la moins fréquente)
#
######################################################################################
# la variable dpe (dernière page exclue) vaut 1 si le verso de la dernière feuille du paquet doit être écarté du document final
# le document final contient alors un nombre pair de pages ; cependant, dpe ne doit pas être utilisée si la dernière feuille du paquet
# a été retirée avant de photocopier les versos

	local paires="${1}" impaires="${2}" toutes="${1}"
	if ${rvc} ; then
		np=$(NbPagesPdf "${toutes}") ;
		dp=$(((${np}+1)/2)) ;
		di=$((${dp}+1+${dpe})) ;
		pi=${np} ;
	else
		dp=$(NbPagesPdf "${paires}") ;
		di=$((1+${dpe})) ;
		pi=$(NbPagesPdf "${impaires}") ;
	fi
	pdftk A="${impaires}" B="${paires}" shuffle A${pi}-${di}${rpv} B2-${dp}${rpr} output ${trv} keep_first_id  2>/tmp/pdftk.err ;
	[[ $((${?})) -ne 0 ]] && Msg_Err e=133 "$(cat /tmp/pdftk.err)" ;
}

function LireParams () {
	
	function yad_form () {
		titre="Les rectos et les versos peuvent être contenus dans un fichier unique (1) ou dans deux fichiers séparés,"
		titre="${titre} l'un pour les rectos (1), l'autre pour les versos (2). Les versos sont dans l'ordre inverse des pages."
		titre="${titre}\nLa possibilité de retourner les pages qui sont éventuellement à l'envers s'applique séparément pour les rectos et"
		titre="${titre} les versos, même lorsque toutes les pages sont dans le même fichier."		
		yad --form --title="Choix du fichier à réordonner" --button="gtk-ok:0"  --button=Annuler:1 \
			--width=900 \
			--text="${titre}" --always-print-result --sticky --center \
			--field="Fichier des rectos ou des rectos et des versos (1):SFL" \
			--field="Ne pas inclure le premier recto (la première page de la photocopie est le premier verso):CHK" \
			--field="Les pages rectos sont à l'envers et doivent être retournées:CHK" \
			--field="Fichier des versos, si rectos et versos séparés (2):SFL" \
			--field="Ne pas inclure le dernier verso:CHK" \
			--field="Les pages versos sont à l'envers et doivent être retournées:CHK" \
			--field="Si aucun fichier n'est spécifié ci-dessous, le fichier des rectos est écrasé:LBL" \
			--field="Fichier à créer (3):SFL" \
			"" "" "" "" "" "" "" ""
		}
	params=$(yad_form) ;
	[ "${?}" != "0" ] && exit 1 ;
	pdf_recto=$(echo "${params}" | cut -d "|" -f 1) ;
	[ -z "${pdf_recto}" ] && Msg_Err e=128 ;
	nbr=$(NbPagesPdf "${pdf_recto}")
	pdf_verso=$(echo "${params}" | cut -d "|" -f 4) ;
	[ -n "${pdf_verso}" ] && rvc=false && nbv=$(NbPagesPdf "${pdf_verso}") || pdf_verso="${pdf_recto}" && nbv=nbr ;
	pdf_cree=$(echo "${params}" | cut -d "|" -f 8) ;
	[ -z "${pdf_cree}" ] && pdf_cree="${pdf_recto}" ;
	[[ "$(echo "${params}" | cut -d "|" -f 2)" = "TRUE" ]] && pri=false ;
	[[ "$(echo "${params}" | cut -d "|" -f 3)" = "TRUE" ]] && rpr=down ;	
	[[ "$(echo "${params}" | cut -d "|" -f 5)" = "TRUE" ]] && dvi=false ;
	[[ "$(echo "${params}" | cut -d "|" -f 6)" = "TRUE" ]] && rpv=down ;
}

function ordonne () {
	Initialisations
	LesOptions
	LesRessources
	! ${opt} && LireParams
	${dvi} && dpe=0 || dpe=1 ;
	trv="$(mktemp)" ;	
	${pri} && rslt="$(Ordonnance_pri "${pdf_recto}" "${pdf_verso}")" ;
	! ${pri} && rslt="$(Ordonnance_pre "${pdf_recto}" "${pdf_verso}")" ;
	cp -fT "${trv}" "${pdf_cree}" && rm "${trv}"
	Msg_Err e=0 "${pdf_cree}"
	return 0
}

"${@}";

Arbiel Perlacremaz
Dell Vostro Ubuntu 18.04 64 bits, LDLC Aurore NK3S-8-S4 Ubuntu 20.04
Abandon d'azerty au profit de bépo, de google au profit de Lilo et de la messagerie électronique violable au profit de Protonmail, une messagerie chiffrée de poste de travail à poste de travail.

Hors ligne