diff --git a/CHANGELOG.md b/CHANGELOG.md
index 62724e6..30f6312 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,48 @@
+## Changelog for release v2.3
+
+**Changes:**
+- Added option `-a/--batch-scan` to allow scanning multiple documents in one
+ go, prompting user in between documents (depends on option
+ `-o/--outfile-pattern` for output file naming)
+- Added option `-o/--outfile-pattern` that allows specifying OUTFILE command
+ line argument as printf-style pattern (e.g. `~/Documents/Scan_%05d.pdf`)
+ that is used to automatically determine the next available output file name
+ by incrementing the integer part of the pattern
+- Reordered configuration items to better highlight which settings to use for
+ which paper size
+- Removed configuration items that only make sense to be modified via command
+ line options from configuration file (`BATCH_SCAN_DEFAULT`,
+ `OUTFILE_PATTERN_DEFAULT`, `KEEP_TEMP_DEFAULT`)
+- Eliminated need to `cd` to temporary directory by adding path to temporary
+ directory to `--batch=` template of call to `scanimage`
+- Added '--' to explicitely end option parsing to all external commands that
+ support it
+- Applied a few minor tweaks to printed output (wording, spacing)
+- Extended headers in script and configuration file to 80 characters
+- Reformatted `README.md` and `CHANGELOG.md` to be more readable when viewed
+ in a simple text viewer/editor
+
+## Changelog for release v2.2
+
+**Changes:**
+- Added support for using `convert` (ImageMagick) instead of `tiff2pdf`
+ (LibTIFF) as the latter is no longer being built by default and will
+ probably be removed completely from from LibTIFF in the foreseable future
+ (see https://bugs.gentoo.org/914232)
+- Added empty lines within usage information group similar items (e.g.
+ brightness + contrast, topleftx + toplefty + width + height, etc.)
+- If an output file is specified, abort if it already exists (instead of
+ overwriting it)
+- If no output file is specified, automatically choose the next available
+ `scan_NNNNN.pdf` file name (i.e. `scan_00001.pdf`, `scan_00002.pdf`, etc.)
+- Use `-e` for output file checks instead of `-f` (to catch non-file items
+ like folders, fifos, sockets, etc. as well)
+
## Changelog for release v2.1
Initial release (versions prior to v2.1 have not been published).
-Features:
+**Features:**
- Highly configurable (both via configuration file and command line options)
- Allows selecting scan source, scan resolution and color mode
- Allows setting brightness and contrast (for color modes that support this)
@@ -11,4 +51,4 @@ Features:
##
-_Last updated: 09/16/23_
+_Last updated: 01/14/24_
diff --git a/README.md b/README.md
index 1cb02a3..c1aaef8 100644
--- a/README.md
+++ b/README.md
@@ -1,37 +1,59 @@
# Scan to PDF (scan2pdf)
-Scan documents directly to PDF file from the command line. Especially useful to batch-scan large volumes.
+Scan documents directly to PDF files from the command line. Especially useful
+to batch-scan large volumes of documents.
## Donations
-I'm striving to become a full-time developer of [Free and open-source software (FOSS)](https://en.wikipedia.org/wiki/Free_and_open-source_software). Donations help me achieve that goal and are highly appreciated.
+I'm striving to become a full-time developer of [Free and open-source software
+(FOSS)](https://en.wikipedia.org/wiki/Free_and_open-source_software). Donations
+help me achieve that goal and are highly appreciated.
-
+
+
+
## Requirements
**Dependencies:**
-_Bash (>=v4.0)_, _scanimage_ (part of [SANE](http://www.sane-project.org/)), _tiffcp_ and _tiff2pdf_ (part of [libtiff](http://libtiff.maptools.org/))
+_Bash (>=v4.0)_,
+_scanimage_ (part of [SANE](http://www.sane-project.org/)),
+_tiffcp_ (part of [LibTIFF](http://libtiff.maptools.org/)),
+_tiff2pdf_ (part of [LibTIFF](http://libtiff.maptools.org/))
+-or-
+_convert_ (part of [ImageMagick](https://www.imagemagick.org/))
**Packages:**
-Ubuntu: _bash_, _sane-utils_, _libtiff-tools_
-Gentoo: _app-shells/bash_, _media-gfx/sane-backends_, _media-libs/tiff_
+Ubuntu: _bash_, _sane-utils_, _libtiff-tools_, _imagemagick_
+Gentoo: _app-shells/bash_, _media-gfx/sane-backends_, _media-libs/tiff_,
+ _media-gfx/imagemagick_
## Download & Installation
-Refer to the [releases](https://github.com/fonic/scan2pdf/releases) section for downloads links. There is no installation required. Simply extract the downloaded archive to a folder of your choice.
+Refer to the [releases](https://github.com/fonic/scan2pdf/releases) section
+for downloads links. There is no actual installation required. Simply extract
+the downloaded archive to a folder of your choice.
## Configuration
-Open `scan2pdf.conf` in your favorite text editor and adjust the settings to your liking. Refer to embedded comments for details. Refer to [this section](#configuration-options--defaults) for a listing of all configuration options and current defaults.
+Open `scan2pdf.conf` in your favorite text editor and adjust the settings
+to your liking. Refer to embedded comments for details. Refer to
+[this section](#configuration-options) for a listing of all configuration
+options and current defaults.
-## Usage
-To scan a document to PDF file, use the following commands:
+## Quick Start
+To scan a single document to PDF file, use the following command:
```
-$ cd scan2pdf-vX.Y
$ ./scan2pdf.sh document.pdf
```
+To scan multiple documents to PDF files, use the following command:
+```
+$ ./scan2pdf.sh -a -o document_%05d.pdf
+```
+
+## Command Line Options
+
Available command line options:
```
Usage: scan2pdf.sh [OPTIONS] OUTFILE
-Scan to PDF (scan2pdf) v2.1 (09/16/23)
+Scan to PDF (scan2pdf) v2.3 (01/14/24)
Scan documents directly to PDF file.
Options:
@@ -50,14 +72,23 @@ Options:
'Automatic Document Feeder(left aligned,Duplex)',
'Automatic Document Feeder(centrally aligned)',
'Automatic Document Feeder(centrally aligned,Duplex)'
+
-b, --brightness VALUE Brightness in percent (-50..50) [0]
(only applied if supported by color mode)
-c, --contrast VALUE Contrast in percent (-50..50) [0]
(only applied if supported by color mode)
+
-l, --topleftx VALUE Top left x offset of scan area in mm (0..216) [0]
-t, --toplefty VALUE Top left y offset of scan area in mm (0..356) [0]
-x, --width VALUE Width of scan area in mm (0..216) [216]
- -y, --height VALUE Height of scan area in mm (0..356) [280]
+ -y, --height VALUE Height of scan area in mm (0..356) [279]
+
+ -a, --batch-scan Scan multiple documents, prompt in between documents
+ (option '-o/--outfile-template' becomes mandatory)
+ -o, --outfile-pattern Interpret OUTFILE argument as printf-style pattern,
+ determine next available output file by incrementing
+ integer component (e.g. '~/Documents/Scan_%05d.pdf')
+
-k, --keep-temp Keep temporary directory on exit
-h, --help Print usage information
@@ -65,26 +96,27 @@ NOTE:
Strings/values in square brackets show current defaults.
```
-## Configuration Options & Defaults
+## Configuration Options
Configuration options and current defaults:
```sh
# scan2pdf.conf
-# -------------------------------------------------------------------------
-# -
-# Scan to PDF (scan2pdf) -
-# -
-# Created by Fonic -
-# Date: 04/17/21 - 09/16/23 -
-# -
-# -------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
+# -
+# Scan to PDF (scan2pdf) -
+# -
+# Created by Fonic -
+# Date: 04/17/21 - 01/14/24 -
+# -
+# ------------------------------------------------------------------------------
# NOTE:
# Turn scanner on and run 'scanimage --help' to get detailed information
# on supported parameters and/or valid values for scan-related settings
# Default scanner device (string)
+#DEVICE_DEFAULT="brother3:net1;dev0"
DEVICE_DEFAULT="brother4:net1;dev0"
# Supported color modes (array of strings), default color mode (string)
@@ -141,13 +173,14 @@ TOPLEFTY_MAX=356
TOPLEFTY_DEFAULT=0
WIDTH_MIN=0
WIDTH_MAX=216
-#WIDTH_DEFAULT=210 # DIN A4 (210.0 mm / 8.3 in)
-WIDTH_DEFAULT=216 # Letter/Legal (215.9 mm / 8.5 in)
HEIGHT_MIN=0
HEIGHT_MAX=356
+#WIDTH_DEFAULT=210 # DIN A4 (210.0 mm / 8.3 in)
#HEIGHT_DEFAULT=297 # DIN A4 (297.0 mm / 11.7 in)
-#HEIGHT_DEFAULT=356 # Legal (355.6 mm / 14.0 in)
-HEIGHT_DEFAULT=280 # Letter (279.4 mm / 11.0 in)
+#WIDTH_DEFAULT=216 # Legal (215.9 mm / 8.5 in)
+#HEIGHT_DEFAULT=356 # Legal (355.6 mm / 14.0 in)
+WIDTH_DEFAULT=216 # Letter (215.9 mm / 8.5 in)
+HEIGHT_DEFAULT=279 # Letter (279.4 mm / 11.0 in)
# Options passed to 'scanimage' (array of strings)
#SCANIMAGE_OPTS=("--progress" "--verbose") # display scan progress, use verbose output
@@ -160,10 +193,14 @@ TIFFCP_OPTS=("-c" "lzw") # use LZW compression (fast)
#TIFF2PDF_OPTS=("-z") # use ZIP compression (lossless, higher quality, bigger PDF file)
TIFF2PDF_OPTS=("-j" "-q" "95") # use JPEG compression (quality 95) (lossy, lower quality, smaller PDF file)
-# Keep temporary directory on exit by default (string, 'yes'/'no')
-KEEPTEMP_DEFAULT="no"
+# Options passed to 'convert' (array of strings)
+# NOTE:
+# 'convert' is only used if 'tiff2pdf' is not available
+# 'convert' uses separate options for INPUT and OUTPUT
+CONVERT_INPUT_OPTS=() # none
+CONVERT_OUTPUT_OPTS=() # none
```
##
-_Last updated: 09/16/23_
+_Last updated: 01/14/24_
diff --git a/scan2pdf.conf b/scan2pdf.conf
index e20aa2b..2989f6e 100644
--- a/scan2pdf.conf
+++ b/scan2pdf.conf
@@ -1,19 +1,20 @@
# scan2pdf.conf
-# -------------------------------------------------------------------------
-# -
-# Scan to PDF (scan2pdf) -
-# -
-# Created by Fonic -
-# Date: 04/17/21 - 09/16/23 -
-# -
-# -------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
+# -
+# Scan to PDF (scan2pdf) -
+# -
+# Created by Fonic -
+# Date: 04/17/21 - 01/14/24 -
+# -
+# ------------------------------------------------------------------------------
# NOTE:
# Turn scanner on and run 'scanimage --help' to get detailed information
# on supported parameters and/or valid values for scan-related settings
# Default scanner device (string)
+#DEVICE_DEFAULT="brother3:net1;dev0"
DEVICE_DEFAULT="brother4:net1;dev0"
# Supported color modes (array of strings), default color mode (string)
@@ -70,13 +71,14 @@ TOPLEFTY_MAX=356
TOPLEFTY_DEFAULT=0
WIDTH_MIN=0
WIDTH_MAX=216
-#WIDTH_DEFAULT=210 # DIN A4 (210.0 mm / 8.3 in)
-WIDTH_DEFAULT=216 # Letter/Legal (215.9 mm / 8.5 in)
HEIGHT_MIN=0
HEIGHT_MAX=356
+#WIDTH_DEFAULT=210 # DIN A4 (210.0 mm / 8.3 in)
#HEIGHT_DEFAULT=297 # DIN A4 (297.0 mm / 11.7 in)
-#HEIGHT_DEFAULT=356 # Legal (355.6 mm / 14.0 in)
-HEIGHT_DEFAULT=280 # Letter (279.4 mm / 11.0 in)
+#WIDTH_DEFAULT=216 # Legal (215.9 mm / 8.5 in)
+#HEIGHT_DEFAULT=356 # Legal (355.6 mm / 14.0 in)
+WIDTH_DEFAULT=216 # Letter (215.9 mm / 8.5 in)
+HEIGHT_DEFAULT=279 # Letter (279.4 mm / 11.0 in)
# Options passed to 'scanimage' (array of strings)
#SCANIMAGE_OPTS=("--progress" "--verbose") # display scan progress, use verbose output
@@ -89,5 +91,9 @@ TIFFCP_OPTS=("-c" "lzw") # use LZW compression (fast)
#TIFF2PDF_OPTS=("-z") # use ZIP compression (lossless, higher quality, bigger PDF file)
TIFF2PDF_OPTS=("-j" "-q" "95") # use JPEG compression (quality 95) (lossy, lower quality, smaller PDF file)
-# Keep temporary directory on exit by default (string, 'yes'/'no')
-KEEPTEMP_DEFAULT="no"
+# Options passed to 'convert' (array of strings)
+# NOTE:
+# 'convert' is only used if 'tiff2pdf' is not available
+# 'convert' uses separate options for INPUT and OUTPUT
+CONVERT_INPUT_OPTS=() # none
+CONVERT_OUTPUT_OPTS=() # none
diff --git a/scan2pdf.sh b/scan2pdf.sh
index e5ef1a7..915e654 100755
--- a/scan2pdf.sh
+++ b/scan2pdf.sh
@@ -1,16 +1,16 @@
#!/usr/bin/env bash
-# -------------------------------------------------------------------------
-# -
-# Scan to PDF (scan2pdf) -
-# -
-# Created by Fonic -
-# Date: 04/17/21 - 09/16/23 -
-# -
-# Based on: -
-# https://gist.github.com/mludvig/936678 -
-# -
-# -------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
+# -
+# Scan to PDF (scan2pdf) -
+# -
+# Created by Fonic -
+# Date: 04/17/21 - 01/14/24 -
+# -
+# Inspired by: -
+# https://gist.github.com/mludvig/936678 -
+# -
+# ------------------------------------------------------------------------------
# --------------------------------------
# -
@@ -33,11 +33,11 @@ fi
# --------------------------------------
# Script information
-SCRIPT_FILE="$(basename "$0")"
-SCRIPT_PATH="$(realpath "$0")"
+SCRIPT_FILE="$(basename -- "$0")"
+SCRIPT_PATH="$(realpath -- "$0")"
SCRIPT_CONF="${SCRIPT_PATH%.*}.conf"
SCRIPT_TITLE="Scan to PDF (scan2pdf)"
-SCRIPT_VERSION="2.1 (09/16/23)"
+SCRIPT_VERSION="2.3 (01/14/24)"
# Usage information
# NOTE:
@@ -56,14 +56,23 @@ Scan documents directly to PDF file.
%{SCAN_RESOLUTIONS}
-s, --source STRING Scan source ['\${SOURCE_DEFAULT}']
%{SCAN_SOURCES}
+
-b, --brightness VALUE Brightness in percent (\${BRIGHTNESS_MIN}..\${BRIGHTNESS_MAX}) [\${BRIGHTNESS_DEFAULT}]
(only applied if supported by color mode)
-c, --contrast VALUE Contrast in percent (\${CONTRAST_MIN}..\${CONTRAST_MAX}) [\${CONTRAST_DEFAULT}]
(only applied if supported by color mode)
+
-l, --topleftx VALUE Top left x offset of scan area in mm (\${TOPLEFTX_MIN}..\${TOPLEFTX_MAX}) [\${TOPLEFTX_DEFAULT}]
-t, --toplefty VALUE Top left y offset of scan area in mm (\${TOPLEFTY_MIN}..\${TOPLEFTY_MAX}) [\${TOPLEFTY_DEFAULT}]
-x, --width VALUE Width of scan area in mm (\${WIDTH_MIN}..\${WIDTH_MAX}) [\${WIDTH_DEFAULT}]
-y, --height VALUE Height of scan area in mm (\${HEIGHT_MIN}..\${HEIGHT_MAX}) [\${HEIGHT_DEFAULT}]
+
+ -a, --batch-scan Scan multiple documents, prompt in between documents
+ (option '-o/--outfile-template' becomes mandatory)
+ -o, --outfile-pattern Interpret OUTFILE argument as printf-style pattern,
+ determine next available output file by incrementing
+ integer component (e.g. '~/Documents/Scan_%05d.pdf')
+
-k, --keep-temp Keep temporary directory on exit
-h, --help Print usage information
@@ -74,10 +83,15 @@ Strings/values in square brackets show current defaults."
# dynamically generated contents, i.e. when replacing '%{...}' tokens)
USAGE_INDENT=28
+# Upper limit for index used to determine next available output file based
+# on output file pattern (100k documents in one folder should be more than
+# enough)
+MAX_INDEX=99999
+
# --------------------------------------
# -
-# Configuration -
+# Default Configuration -
# -
# --------------------------------------
@@ -86,6 +100,7 @@ USAGE_INDENT=28
# on supported parameters and/or valid values for scan-related settings
# Default scanner device (string)
+#DEVICE_DEFAULT="brother3:net1;dev0"
DEVICE_DEFAULT="brother4:net1;dev0"
# Supported color modes (array of strings), default color mode (string)
@@ -142,13 +157,14 @@ TOPLEFTY_MAX=356
TOPLEFTY_DEFAULT=0
WIDTH_MIN=0
WIDTH_MAX=216
-#WIDTH_DEFAULT=210 # DIN A4 (210.0 mm / 8.3 in)
-WIDTH_DEFAULT=216 # Letter/Legal (215.9 mm / 8.5 in)
HEIGHT_MIN=0
HEIGHT_MAX=356
+#WIDTH_DEFAULT=210 # DIN A4 (210.0 mm / 8.3 in)
#HEIGHT_DEFAULT=297 # DIN A4 (297.0 mm / 11.7 in)
-#HEIGHT_DEFAULT=356 # Legal (355.6 mm / 14.0 in)
-HEIGHT_DEFAULT=280 # Letter (279.4 mm / 11.0 in)
+#WIDTH_DEFAULT=216 # Legal (215.9 mm / 8.5 in)
+#HEIGHT_DEFAULT=356 # Legal (355.6 mm / 14.0 in)
+WIDTH_DEFAULT=216 # Letter (215.9 mm / 8.5 in)
+HEIGHT_DEFAULT=279 # Letter (279.4 mm / 11.0 in)
# Options passed to 'scanimage' (array of strings)
#SCANIMAGE_OPTS=("--progress" "--verbose") # display scan progress, use verbose output
@@ -161,8 +177,27 @@ TIFFCP_OPTS=("-c" "lzw") # use LZW compression (fast)
#TIFF2PDF_OPTS=("-z") # use ZIP compression (lossless, higher quality, bigger PDF file)
TIFF2PDF_OPTS=("-j" "-q" "95") # use JPEG compression (quality 95) (lossy, lower quality, smaller PDF file)
+# Options passed to 'convert' (array of strings)
+# NOTE:
+# 'convert' is only used if 'tiff2pdf' is not available
+# 'convert' uses separate options for INPUT and OUTPUT
+CONVERT_INPUT_OPTS=() # none
+CONVERT_OUTPUT_OPTS=() # none
+
+# Scan multiple documents, prompt user in between documents by default
+# (string, 'yes'/'no')
+BATCH_SCAN_DEFAULT="no"
+
+# Interpret OUTFILE command line argument as printf-style pattern and de-
+# termine next output file automatically by incrementing integer component
+# of pattern by default (string, 'yes'/'no')
+# Example:
+# Pattern '~/Documents/Scan_%05d.pdf' -> '~/Documents/Scan_00001.pdf',
+# '~/Documents/Scan_00002.pdf', '~/Documents/Scan_00003.pdf', ...
+OUTFILE_PATTERN_DEFAULT="no"
+
# Keep temporary directory on exit by default (string, 'yes'/'no')
-KEEPTEMP_DEFAULT="no"
+KEEP_TEMP_DEFAULT="no"
# --------------------------------------
@@ -286,7 +321,7 @@ function is_integer() {
set -ueE; trap "printe \"Error: an unhandled error occurred on line \${LINENO}, aborting\"; exit 1" ERR
# Set up trap to handle CTRL+C/SIGINT
-trap "set +e; trap - ERR; echo -en \"\r\e[2K\"; printw \"Aborting per user request (CTRL+C/SIGINT)\"; exit 130" INT
+trap "set +e; trap - ERR; echo -en \"\r\e[2K\"; printn; printw \"Aborting per user request (CTRL+C/SIGINT).\"; exit 130" INT
# Source configuration
if ! source "${SCRIPT_CONF}"; then
@@ -325,7 +360,7 @@ printn
trap "printn" EXIT
# Initialize settings with defaults
-for item in device mode resolution source brightness contrast topleftx toplefty width height keeptemp; do
+for item in device mode resolution source brightness contrast topleftx toplefty width height outfile_pattern batch_scan keep_temp; do
declare -n setvar="${item}"
declare -n defvar="${item^^}_DEFAULT"
setvar="${defvar}"
@@ -375,8 +410,14 @@ while getopt option; do
getarg height || { printe "Error: option '${option}' requires an argument"; result=1; continue; }
is_integer "${height}" ${HEIGHT_MIN} ${HEIGHT_MAX} || { printe "Error: invalid height value '${height}'"; result=1; continue; }
;;
+ -a|--batch-scan)
+ batch_scan="yes"
+ ;;
+ -o|--outfile-pattern)
+ outfile_pattern="yes"
+ ;;
-k|--keep-temp)
- keeptemp="yes"
+ keep_temp="yes"
;;
-h|--help)
# already handled above
@@ -391,18 +432,31 @@ while getopt option; do
;;
esac
done
-[[ -n "${outfile+set}" ]] || { printe "Error: no output file specified"; result=1; }
+[[ "${batch_scan}" == "yes" && "${outfile_pattern}" != "yes" ]] && { printe "Error: option '-a/--batch-scan' requires option '-o/--outfile-pattern'"; result=1; }
+if [[ "${outfile_pattern}" == "yes" ]]; then
+ if [[ -n "${outfile+set}" ]]; then
+ [[ "${outfile}" =~ %[0-9]*d ]] || { printe "Error: invalid output file pattern '${outfile}' (integer token missing)"; result=1; }
+ else
+ printe "Error: no output file pattern specified"; result=1
+ fi
+else
+ if [[ -n "${outfile+set}" ]]; then
+ [[ -e "${outfile}" ]] && { printe "Error: output file '${outfile}' already exists"; result=1; }
+ else
+ printe "Error: no output file specified"; result=1
+ fi
+fi
(( ${result} == 0 )) || { printe "Error: invalid command line, use '--help' to display usage information"; exit 2; }
# Check command availability
result=0
-for cmd in scanimage tiffcp tiff2pdf; do
- is_cmd_avail "${cmd}" || { printe "Error: command '${cmd}' is not available"; result=1; }
-done
+is_cmd_avail "scanimage" || { printe "Error: command 'scanimage' is not available"; result=1; }
+is_cmd_avail "tiffcp" || { printe "Error: command 'tiffcp' is not available"; result=1; }
+is_cmd_avail "tiff2pdf" || is_cmd_avail "convert" || { printe "Error: neither command 'tiff2pdf' nor 'convert' is available"; result=1; }
(( ${result} == 0 )) || { printe "Error: missing required command(s), check dependencies"; exit 1; }
-# Print scan settings
-printh "Scan settings:"
+# Print scan parameters
+printh "Scan parameters:"
printn "Device: ${device}"
printn "Mode: ${mode}"
printn "Resolution: ${resolution} dpi"
@@ -413,55 +467,103 @@ printn "Top left x: ${topleftx} mm"
printn "Top left y: ${toplefty} mm"
printn "Width: ${width} mm"
printn "Height: ${height} mm"
-printn "Keep temp: ${keeptemp}"
-printn "Output file: ${outfile}"
+printn "Keep temp: ${keep_temp}"
+[[ "${outfile_pattern}" != "yes" ]] && printn "Output file: ${outfile}"
+printn
# Create temporary directory, set up exit trap for cleanup (replaces pre-
# viously set up cosmetic exit trap)
printh "Creating temporary directory..."
tempdir="$(mktemp -d)" || { printe "Error: failed to create temporary directory, aborting"; exit 1; }
-trap "set +e; trap - ERR; if [[ \"${keeptemp}\" == \"yes\" ]]; then printw \"Keeping temporary directory '${tempdir}'\"; else rm -rf \"${tempdir}\"; fi; printn" EXIT
+trap "set +e; trap - ERR; if [[ \"${keep_temp}\" == \"yes\" ]]; then printn; printw \"Keeping temporary directory '${tempdir}'.\"; else rm -rf -- \"${tempdir}\"; fi; printn" EXIT
printn "Path: ${tempdir}"
+printn
-# Scan pages (creates one TIFF file per page)
-# NOTE:
-# Using file name template 'page_%010d.tiff' ('page_0000000001.tiff', 'page_
-# 0000000002.tiff', etc.) to maintain correct page order when passing files
-# to 'tiffcp' using 'page_*.tiff' below
-printh "Scanning pages..."
-opts=()
-opts+=("--device-name=${device}")
-opts+=("--mode=${mode}")
-opts+=("--resolution=${resolution}")
-opts+=("--source=${source}")
-in_array "${mode}" BRIGHTNESS_MODES && opts+=("--brightness=${brightness}")
-in_array "${mode}" CONTRAST_MODES && opts+=("--contrast=${contrast}")
-opts+=("-l" "${topleftx}")
-opts+=("-t" "${toplefty}")
-opts+=("-x" "${width}")
-opts+=("-y" "${height}")
-opts+=("--format=tiff")
-opts+=("--batch=page_%010d.tiff")
-opts+=("${SCANIMAGE_OPTS[@]}")
-print_cmd "scanimage" "${opts[@]}"
-cd "${tempdir}" || { printe "Error: failed to change directory to '${tempdir}', aborting"; exit 1; }
-scanimage "${opts[@]}" || { printe "Error: call to 'scanimage' failed (exit code: $?), aborting"; exit 1; }
-cd - >/dev/null || :
-
-# Merge pages (creates multipage TIFF file)
-printh "Merging pages..."
-opts=("${TIFFCP_OPTS[@]}")
-opts+=("${tempdir}"/page_*.tiff "${tempdir}/multipage.tiff")
-print_cmd "tiffcp" "${opts[@]}"
-tiffcp "${opts[@]}" || { printe "Error: call to 'tiffcp' failed (exit code: $?), aborting"; exit 1; }
-
-# Create PDF file (from multipage TIFF file)
-printh "Creating PDF..."
-opts=("${TIFF2PDF_OPTS[@]}")
-opts+=("${tempdir}/multipage.tiff" "-o" "${outfile}")
-print_cmd "tiff2pdf" "${opts[@]}"
-tiff2pdf "${opts[@]}" || { printe "Error: call to 'tiff2pdf' failed (exit code: $?), aborting"; exit 1; }
-
-# Return home safely
-printg "Success, all done."
-exit 0
+# Batch scan loop (only executed ONCE if not batch-scanning)
+result=0; index=0; pattern="${outfile}"
+while true; do
+
+ # Determine next available output file based on output file pattern?
+ if [[ "${outfile_pattern}" == "yes" ]]; then
+ printh "Determining next output file..."
+ for ((index++; index <= ${MAX_INDEX}; index++)); do
+ printf -v outfile "${pattern}" "${index}"
+ [[ -e "${outfile}" ]] || break
+ done
+ if (( ${index} > ${MAX_INDEX} )) || [[ -e "${outfile}" ]]; then
+ printe "Error: failed to determine next output file (last candidate: ${outfile})"; result=1; break
+ fi
+ printn "Output file: ${outfile}"
+ fi
+
+ # Determine file name of output file (without leading path and extension)
+ # NOTE:
+ # Used to name TIFF files in temporary directory to avoid name clashing
+ # while still having recognizable file names if user chooses to inspect
+ # contents (using option '-k/--keep-temp')
+ outfile_name="${outfile##*/}"; outfile_name="${outfile_name%.*}"
+
+ # Scan pages (creates one TIFF file per page)
+ # NOTE:
+ # Using file name template '_page_%05d.tiff' ('_page_00001.tiff', '_page_
+ # 00002.tiff', etc.) to maintain correct page order when passing files to
+ # 'tiffcp' using '_page_*.tiff' below
+ printh "Scanning pages..."
+ opts=()
+ opts+=("--device-name=${device}")
+ opts+=("--mode=${mode}")
+ opts+=("--resolution=${resolution}")
+ opts+=("--source=${source}")
+ in_array "${mode}" BRIGHTNESS_MODES && opts+=("--brightness=${brightness}")
+ in_array "${mode}" CONTRAST_MODES && opts+=("--contrast=${contrast}")
+ opts+=("-l" "${topleftx}")
+ opts+=("-t" "${toplefty}")
+ opts+=("-x" "${width}")
+ opts+=("-y" "${height}")
+ opts+=("--format=tiff")
+ opts+=("--batch=${tempdir}/${outfile_name}_page_%05d.tiff")
+ opts+=("${SCANIMAGE_OPTS[@]}")
+ print_cmd "scanimage" "${opts[@]}"
+ scanimage "${opts[@]}" || { printe "Error: call to 'scanimage' failed (exit code: $?), aborting"; result=1; break; }
+
+ # Merge pages (creates multipage TIFF file)
+ printh "Merging pages..."
+ opts=()
+ opts+=("${TIFFCP_OPTS[@]}")
+ opts+=("--")
+ opts+=("${tempdir}/${outfile_name}_page_"*.tiff)
+ opts+=("${tempdir}/${outfile_name}_multipage.tiff")
+ print_cmd "tiffcp" "${opts[@]}"
+ tiffcp "${opts[@]}" || { printe "Error: call to 'tiffcp' failed (exit code: $?), aborting"; result=1; break; }
+
+ # Create PDF file (from multipage TIFF file)
+ printh "Creating PDF..."
+ if is_cmd_avail "tiff2pdf"; then
+ opts=()
+ opts+=("${TIFF2PDF_OPTS[@]}")
+ opts+=("-o" "${outfile}")
+ opts+=("--")
+ opts+=("${tempdir}/${outfile_name}_multipage.tiff")
+ print_cmd "tiff2pdf" "${opts[@]}"
+ tiff2pdf "${opts[@]}" || { printe "Error: call to 'tiff2pdf' failed (exit code: $?), aborting"; result=1; break; }
+ elif is_cmd_avail "convert"; then
+ opts=()
+ opts+=("${CONVERT_INPUT_OPTS[@]}")
+ opts+=("${tempdir}/${outfile_name}_multipage.tiff")
+ opts+=("${CONVERT_OUTPUT_OPTS[@]}")
+ opts+=("${outfile}")
+ print_cmd "convert" "${opts[@]}"
+ convert "${opts[@]}" || { printe "Error: call to 'convert' failed (exit code: $?), aborting"; result=1; break; }
+ fi
+
+ # Prompt user to continue batch scan with next document?
+ [[ "${batch_scan}" != "yes" ]] && break
+ printn
+ printw "Prepare next document and hit ENTER to continue -or- hit CTRL+D to exit."
+ read -s || break
+ printn
+
+done
+
+# Return result
+exit ${result}