Hallo,
bevor die Programmiererfahrenen die Hände über den Köpfen zusammenschlagen: Ja! - Das ist nicht herausragend programmiert und das würde ich in dieser Form so auch nicht im AUR publizieren! Aber wegen der Nachfrage:
Es geht im folgende Problemstellung. Ich habe zu Hause einen Drucker (Modell brother HL-3040CN), mit dem ich
einseitig drucken kann. Ich drucke mir ganz gerne Mathematikskripte von der Uni im Format DIN-A-6 aus. Ich muss nun also vier Seiten des Skriptes auf ein DIN-A-4-Blatt drucken. Auch die Rückseiten sollen bedruckt werden. Dazu muss man quasi die Hälfte der Seiten auf die Vorderseiten der DIN-A-4-Blätter drucken, dann diesen bedruckten Papierstapel
richtig in den Drucker einlegen, sodaß die auch die Rückseiten gedruckt werden können. Die Kunst besteht nun darin die richtigen Rückseiten auf die dazugehörigen Vorderseiten zu drucken. Es sollen aber nicht nur die passenden Rückseiten auf die komplentären Vorderseiten gerdruckt werden, sondern der Druck soll auch so erfolgen, daß ich die fertigen DIN-A4-Blätter alle übereinander legen und zu DIN-A6 zerschneiden kann und die fertigen Stapel dann auch nur noch aufeinander legen muss (und nicht noch die ganzen Seiten sortieren muss). Beim Übereinanderlegen muss man manchmal mit der letzten Seite aufpassen, wenn man 2 Seiten Rest hat (modulo) 8, dann würde man die Rückseite der letzten Seite um eins versetzt drucken. Muss dann also eine Füllseite drucken um das ganze zu shiften.
Beispiel:
./slpr -6sn <Pfad zur .pdf-Datei>
(6 für DIN-A6; es können auch 4 und 5 für Din-A4 bzw. Din-A5-Format gewählt werden). Dieses Beispiel gibt eine Zahlenfolge für die zu druckenden Seiten aus, die z.B: in evince ins Druckmenü kopiert werden kann. s steht für split und teilt in zwei Zahlenfolgen für Vorder- und Rückseiten auf. Statt n kann man auch f schreiben. Dann wird je eine permutierte .pdf-Datei angelegt (für Vorder- und Rückseiten), bei der man quasi normal drucken kann, weil die Seiten ja umsortiert wurden (benötigt stapler aus dem AUR). Und mit p statt n wird diese permutierte .pdf-Datei direkt an lpr weitergegeben.
und das ist das Skript:
#!/bin/bash
# -----------------------------------------------------------------------------
# --- slpr.sh 13.08.2014 ---
# --- Name: slpr ---
# -----------------------------------------------------------------------------
# --- 0.) Ein paar Farbdefinitionen: ------------------------------------------
# -----------------------------------------------------------------------------
A="\033[1;31m" # Farbe für Fehlermeldungen
B="\033[1;34m" # Farbe für Warnungen
C="\033[1;32m" # Farbe für Meldungen
S="\033[0m" # schwarz
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# --- 1.) Funktionen: --------------------------------------------------------
# --- I.) Funktionen für Din-A4-Druck: ----------------------------------------
V4_1() {
n="$1"
case $n in
1) echo "1"
;;
*) l=$(( n - 1 ))
echo $((( $(V4_1 $l) + 2 )))
;;
esac
}
V4_2() {
n="$1"
case $n in
1) echo $((( q + 1 )))
;;
esac
}
R4_1() {
n="$1"
case $n in
1) echo "2"
;;
*) l=$(( n - 1 ))
echo $((( $(R4_1 $l) + 2 )))
;;
esac
}
R4_2() {
n="$1"
}
# --- II.) Funktionen für Din-A5-Druck: ---------------------------------------
V5_1() {
n="$1"
case $n in
1) echo "1"
;;
2) echo $((( q / 2 + 1 )))
;;
*) l=$(( n - 2 ))
echo $((( $(V5_1 $l) + 2 )))
;;
esac
}
V5_2() {
n="$1"
case $n in
1) echo $((( q + 1 )))
;;
2) echo $((( q + 1 )))
;;
3) echo $((( q + 3 ))) $((( q + 1 )))
;;
esac
}
R5_1() {
n="$1"
case $n in
1) echo $((( q / 2 + 2 )))
;;
2) echo "2"
;;
*) l=$(( n - 2 ))
echo $((( $(R5_1 $l) + 2)))
;;
esac
}
R5_2() {
n="$1"
case $n in
2) echo $((( q + 2 ))) $((( q + 2 )))
;;
3) echo $((( q + 2 )))
;;
esac
}
# --- III.) Funktionen für Din-A6-Druck: --------------------------------------
V6_1() { # Vorderseiten (ohne die Restseiten modulo 8)
n="$1"
case $n in
1) echo "1"
;;
2) echo $((( q / 4 + 1 )))
;;
3) echo $((( 2*q / 4 + 1 )))
;;
4) echo $((( 3*q / 4 + 1 )))
;;
*) l=$(( n - 4 ))
echo $((( $(V6_1 $l) + 2 )))
;;
esac
}
V6_2() { # Unterscheidung: restliche Vorderseiten
n="$1"
case $n in
1) echo $((( q + 1 )))
;;
2) echo $((( q + 1 )))
;;
3) v=( $((( q + 3 ))) $((( q + 1 ))) )
echo ${v[*]}
;;
4) v=( $((( q + 1 ))) $((( q + 3 ))) )
echo ${v[*]}
;;
5) v=( $((( q + 1 ))) $((( q + 3 ))) $((( q + 5 ))) )
echo ${v[*]}
;;
6) v=( $((( q + 1 ))) $((( q + 3 ))) $((( q + 5 ))) $((( q + 5 ))) )
echo ${v[*]}
;;
7) v=( $((( q + 1 ))) $((( q + 3 ))) $((( q + 5 ))) $((( q + 7 ))) )
echo ${v[*]}
;;
esac
}
R6_1() { # Rückseiten (ohne die Restseiten modulo 8)
n="$1"
case $n in
1) echo $((( q / 4 + 2 )))
;;
2) echo "2"
;;
3) echo $((( 3*q / 4 + 2 )))
;;
4) echo $((( 2*q / 4 + 2 )))
;;
*) l=$(( n - 4 ))
echo $((( $(R6_1 $l) + 2 )))
;;
esac
}
R6_2() { # Unterscheidung: restliche Rückseiten
n="$1"
case $n in
2) v=( $((( q + 2 ))) $((( q + 2 ))) )
echo ${v[*]}
;;
3) v=( $((( q + 2 ))) )
echo ${v[*]}
;;
4) v=( $((( q + 4 ))) $((( q + 2 ))) )
echo ${v[*]}
;;
5) v=( $((( q + 4 ))) $((( q + 2 ))) )
echo ${v[*]}
;;
6) v=( $((( q + 4 ))) $((( q + 2 ))) $((( q + 6 ))) )
echo ${v[*]}
;;
7) v=( $((( q + 4 ))) $((( q + 2 ))) $((( q + 6 ))) $((( q + 6 ))) )
echo ${v[*]}
;;
esac
}
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# --- 2.) Optionen abklappern: ------------------------------------------------
# -----------------------------------------------------------------------------
PN=$(basename $0) # Name des Skriptes (ohne Pfad)
ARGS=$(getopt --name "$PN" --long dina4,dina5,dina6,numbers,file,print,split \
--options 456nfps -- "$@")
eval set -- $ARGS
# --- Standard-Optionen (wenn keine Parameter eingegeben sind):
vind=4 # vind: Papierformat; Index
nuup=1 # nuup: Seiten pro Blatt
sepb=2 # sepb: Seiten pro Blatt
while [ $# -gt 0 ]; do
case "$1" in
-4 | --dina4) vind=4
nuup=1
sepb=2
;;
-5 | --dina5) vind=5
nuup=2
sepb=4
;;
-6 | --dina6) vind=6
nuup=4
sepb=8
;;
-n | --numbers) a3=3 # a3 bezieht sich auf untenstehendes Array
;;
-f | --file) a6=6
;;
-p | --print) a9=9
;;
-s | --split) s1=1 # s1 nur zur Unterscheidung "s" wahr/falsch
;;
--) shift; break;;
esac
shift
done
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# --- 3.) Befehle unter Berücksichtigung der Optionen abklappern: ------------
# ----------------------------------------------------------------------------
if [ $# -ne 1 ] # genau ein Argument (Pfad zur .pdf-Datei)
then
echo -e "${A}Fehler:${S} Argument benötigt (Pfad zur .pdf-Datei)"
exit 2
else
pdat=$1
fi
p=$(pdfinfo -meta ${pdat} | grep "Pages:" | awk '{print $2}') # Seitenzahl
q=$((( ${sepb}*(${p} / ${sepb}) ))) # größtes durch sepb teilbares Ganzes
r=$((( ${p} - ${q} ))) # Rest modulo sepb
vseiten=()
rseiten=()
# gseiten=()
i=0
while [ $i -lt $((( q / 2))) ] ; do
i=$((( i + 1 )))
j=($(R${vind}_1 $i))
k=($(V${vind}_1 $i))
rseiten+=($j) # Version ohne Komma für stapler
vseiten+=($k)
# gseiten+=($j $k)
done
rseiten+=($(R${vind}_2 $r)) # und die Restseiten
vseiten+=($(V${vind}_2 $r))
# --- erzeugt Zufallszahl für zufälligen Dateinamen:
zufallsf="scale=15; ${RANDOM}/32767"
zufallsz=$(echo ${zufallsf} | bc | tr . _)
slpra=(""
"echo -e \033[1;34m(DIN A${vind}) Rückseiten: \033[m\n${rseiten[*]}"
"echo -e \033[1;34m(DIN A${vind}) Vorderseiten:\033[m\n${vseiten[*]}"
"echo -e \033[1;34m(DIN A${vind}) Seiten: \033[m\n${gseiten[*]}"
"stapler sel $1 ${rseiten[*]} ${1%.pdf}_slpr_R_A${vind}${zufallsz}.pdf"
"stapler sel $1 ${vseiten[*]} ${1%.pdf}_slpr_V_A${vind}${zufallsz}.pdf"
"stapler sel $1 ${gseiten[*]} ${1%.pdf}_slpr_G_A${vind}${zufallsz}.pdf"
"lpr -o number-up=${nuup} ${1%.pdf}_slpr_R_A${vind}${zufallsz}.pdf"
"lpr -o number-up=${nuup} ${1%.pdf}_slpr_V_A${vind}${zufallsz}.pdf"
"lpr -o number-up=${nuup} ${1%.pdf}_slpr_G_A${vind}${zufallsz}.pdf"
)
if [ ! $a3 ] && [ ! $a6 ] && [ ! $a9 ]
then
echo -e "${A}Fehler:${S} Option benötigt"
echo -e " drucken: -p (--print) | in Datei drucken: -f (--file) | Zahlenfolge: -n (--numbers)"
fi
if [ $s1 ] # wenn -s als optionales Argument angegeben.
then
if [ $a3 ] # wenn -n als optionales Argument angegeben,
then unset a3 # dann auftrennen der Zeichenkette in
a1=1 # Rück- und
a2=2 # Vorderseiten.
fi
if [ $a6 ] # wenn -f als optionales Argument angegeben,
then f6=a6 # Option -f mit Variable f6 markieren, um späteres
unset a6 # löschen der Ausgabe zu unterbinden und Datei in
a4=4 # Rück- und
a5=5 # Vorderseiten auftrennen.
fi
if [ $a9 ] # wenn -p als optionales Argument angegeben,
then unset a9 # dann auftrennen des Druckbefehles in
a7=7 # Rück- und
a8=8 # Vorderseiten.
if [ ! $a6 ] # wenn -f nicht als optionales Argument ang.,
then # dann Auftrennen der Datei in
a4=4 # Vorder- und
a5=5 # Rückseiten ohne Markierung der Opt -f durch f6
fi # Die Dateien werden wieder gelöscht.
fi
else # else gibts net.
echo -e "${A}Fehler:${S} Die Funktion für Drucker mit Duplex-Druck gibt's, wenn ich einen habe."
echo -e " Benutzen Sie die Option -s (--split) um Rück- und Vorderseiten getrennt zu drucken."
exit 2
# else # wenn -s nicht als optionales Argument angegeben.
# if [ $a6 ] # wenn -f als optionales Argument angegeben,
# then f6=a6 # Option -f mit Variable f6 markieren.
# fi
fi
for i in 1 2 3 4 5 6 7 9 ; do # 8 ausgelassen, da bei Rückseitendruck Bestätigung.
${slpra[a$i]}
done
if [ $a8 ] # Option a8 tritt nur auf bei getrenntem Druck von
then # Rück- und Vorderseiten, dann Bestätigung abfragen.
echo -e "${C}Bitte die Blätter für den Druck der Rückseiten erneut einlegen!${S}\a"
read -p "fertig? (J,n) " ANT
case $ANT in
(Yes|yes|Y|y|Ja|ja|J|j|"") ${slpra[8]}
;;
(No|no|N|n|Nein|nein) echo -e "${A}Abbruch${S} (durch den Benutzer)"
;;
esac
fi
if [ ! $f6 ] # wenn die Option -f nicht mit f6 markiert ist, dann
then
for i in R V G ; do # werden die zum Druck benötigten Dateien wieder
if [ -f ${1%.pdf}_slpr_${i}_A${vind}${zufallsz}.pdf ] # gelöscht.
then rm -r ${1%.pdf}_slpr_${i}_A${vind}${zufallsz}.pdf
fi
done
fi
Das Skript hat aber noch tausend Unzulänglichkeiten. Zum Beispiel dauert bei einem ~600 Seiten-Dokument das Erstellen der Zahlenfolge vergleichweise lange, weil eben viel in der bash gerechnet wird und eigentlich sollte man so Rechenintensive Sachen auch nicht mit einem bash-Skript lösen, aber da waren eben Zeitaufwand beim Programmieren und Unzulänglichkeiten des Programmierers die limitierenden Faktoren. 🙂