Bash Script to scale and/or resize PDFs from the command line.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

1241 line
41 KiB

  1. #!/usr/bin/env bash
  2. # pdfScale.sh
  3. #
  4. # Scale PDF to specified percentage of original size.
  5. #
  6. # Gustavo Arnosti Neves - 2016 / 07 / 10
  7. # Latest Version - 2017 / 05 / 14
  8. #
  9. # This script: https://github.com/tavinus/pdfScale
  10. # Based on: http://ma.juii.net/blog/scale-page-content-of-pdf-files
  11. # And: https://gist.github.com/MichaelJCole/86e4968dbfc13256228a
  12. VERSION="2.0.0"
  13. ###################### EXTERNAL PROGRAMS #######################
  14. GSBIN="" # GhostScript Binary
  15. BCBIN="" # BC Math Binary
  16. IDBIN="" # Identify Binary
  17. PDFINFOBIN="" # PDF Info Binary
  18. MDLSBIN="" # MacOS mdls Binary
  19. ##################### ENVIRONMENT SET-UP #######################
  20. LC_MEASUREMENT="C" # To make sure our numbers have .decimals
  21. LC_ALL="C" # Some languages use , as decimal token
  22. LC_CTYPE="C"
  23. LC_NUMERIC="C"
  24. TRUE=0 # Silly stuff
  25. FALSE=1
  26. ########################### GLOBALS ############################
  27. SCALE="0.95" # scaling factor (0.95 = 95%, e.g.)
  28. VERBOSE=0 # verbosity Level
  29. PDFSCALE_NAME="$(basename $0)" # simplified name of this script
  30. OSNAME="$(uname 2>/dev/null)" # Check where we are running
  31. JUST_IDENTIFY=$FALSE # Flag to just show PDF info
  32. ADAPTIVEMODE=$TRUE # Automatically try to guess best mode
  33. AUTOMATIC_SCALING=$TRUE # Default scaling in $SCALE, override by resize mode
  34. MODE="" # Which page size detection to use
  35. RESIZE_PAPER_TYPE="" # Pre-defined paper to use
  36. CUSTOM_RESIZE_PAPER=$FALSE # If we are using a custom-defined paper
  37. FLIP_DETECTION=$TRUE # If we shoudl run the Flip-detection
  38. FLIP_FORCE=$FALSE # If we should force Flipping
  39. AUTO_ROTATION='/PageByPage' # GS cal auto-rotation setting
  40. PGWIDTH="" # Input PDF Page Width
  41. PGHEIGHT="" # Input PDF Page Height
  42. RESIZE_WIDTH="" # Resized PDF Page Width
  43. RESIZE_HEIGHT="" # Resized PDF Page Height
  44. ########################## EXIT FLAGS ##########################
  45. EXIT_SUCCESS=0
  46. EXIT_ERROR=1
  47. EXIT_INVALID_PAGE_SIZE_DETECTED=10
  48. EXIT_FILE_NOT_FOUND=20
  49. EXIT_INPUT_NOT_PDF=21
  50. EXIT_INVALID_OPTION=22
  51. EXIT_NO_INPUT_FILE=23
  52. EXIT_INVALID_SCALE=24
  53. EXIT_MISSING_DEPENDENCY=25
  54. EXIT_IMAGEMAGIK_NOT_FOUND=26
  55. EXIT_MAC_MDLS_NOT_FOUND=27
  56. EXIT_PDFINFO_NOT_FOUND=28
  57. EXIT_TEMP_FILE_EXISTS=40
  58. EXIT_INVALID_PAPER_SIZE=50
  59. ############################# MAIN #############################
  60. # Main function called at the end
  61. main() {
  62. checkDeps
  63. printPDFSizes
  64. vprint " Input File: $INFILEPDF"
  65. vprint " Output File: $OUTFILEPDF"
  66. getPageSize
  67. vPrintPageSizes ' Source'
  68. local finalRet=$EXIT_ERROR
  69. local tempFile=""
  70. local tempSuffix="$RANDOM$RANDOM""_TEMP_$RANDOM$RANDOM.pdf"
  71. if isMixedMode; then
  72. outputFile="$OUTFILEPDF" # backup outFile name
  73. tempFile="${OUTFILEPDF%.pdf}.$tempSuffix" # set a temp file name
  74. if isFile "$tempFile"; then
  75. printError $'Error! Temporary file name already exists!\n'"File: $tempFile"$'\nAborting execution to avoid overwriting the file.\nPlease Try again...'
  76. exit $EXIT_TEMP_FILE_EXISTS
  77. fi
  78. OUTFILEPDF="$tempFile" # set output to tmp file
  79. pageResize # resize to tmp file
  80. finalRet=$?
  81. INFILEPDF="$tempFile" # get tmp file as input
  82. OUTFILEPDF="$outputFile" # reset final target
  83. PGWIDTH=$RESIZE_WIDTH # we already know the new page size
  84. PGHEIGHT=$RESIZE_HEIGHT # from the last command (Resize)
  85. vPrintPageSizes ' New'
  86. vPrintScaleFactor
  87. pageScale # scale the resized pdf
  88. finalRet=$(($finalRet+$?))
  89. # remove tmp file
  90. rm "$tempFile" >/dev/null 2>&1 || printError "Error when removing temporary file: $tempFile"
  91. elif isResizeMode; then
  92. vPrintScaleFactor "Disabled (resize only)"
  93. pageResize
  94. finalRet=$?
  95. else
  96. local scaleMode=""
  97. isManualScaledMode && scaleMode='(manual)' || scaleMode='(auto)'
  98. vPrintScaleFactor "$SCALE $scaleMode"
  99. pageScale
  100. finalRet=$?
  101. fi
  102. if [[ finalRet -eq $EXIT_SUCCESS ]]; then
  103. vprint " Final Status: File created successfully"
  104. else
  105. vprint " Final Status: Errors were detected. Exit status: $finalRet"
  106. fi
  107. return $finalRet
  108. }
  109. # Prints PDF Info and exits with $EXIT_SUCCESS
  110. printPDFSizes() {
  111. if [[ $JUST_IDENTIFY -eq $TRUE ]]; then
  112. VERBOSE=0
  113. printVersion 3 " - Paper Sizes"
  114. getPageSize || initError "Could not get pagesize!"
  115. printf " File: %+8s \n" "$(basename "$INFILEPDF")"
  116. printf " Points: %+8s x %-8s\n" "$PGWIDTH" "$PGHEIGHT"
  117. printf " Milimeters: %+8s x %-8s\n" "$(pointsToMilimeters $PGWIDTH)" "$(pointsToMilimeters $PGHEIGHT)"
  118. printf " Inches: %+8s x %-8s\n" "$(pointsToInches $PGWIDTH)" "$(pointsToInches $PGHEIGHT)"
  119. exit $EXIT_SUCCESS
  120. fi
  121. }
  122. ###################### GHOSTSCRIPT CALLS #######################
  123. # Runs the ghostscript scaling script
  124. pageScale() {
  125. # Compute translation factors (to center page).
  126. XTRANS=$(echo "scale=6; 0.5*(1.0-$SCALE)/$SCALE*$PGWIDTH" | "$BCBIN")
  127. YTRANS=$(echo "scale=6; 0.5*(1.0-$SCALE)/$SCALE*$PGHEIGHT" | "$BCBIN")
  128. vprint " Translation X: $XTRANS"
  129. vprint " Translation Y: $YTRANS"
  130. local increase=$(echo "scale=0; (($SCALE - 1) * 100)/1" | "$BCBIN")
  131. vprint " Run Scaling: $increase %"
  132. # Scale page
  133. "$GSBIN" \
  134. -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dSAFER \
  135. -dCompatibilityLevel="1.5" -dPDFSETTINGS="/printer" \
  136. -dColorConversionStrategy=/LeaveColorUnchanged \
  137. -dSubsetFonts=true -dEmbedAllFonts=true \
  138. -dDEVICEWIDTHPOINTS=$PGWIDTH -dDEVICEHEIGHTPOINTS=$PGHEIGHT \
  139. -sOutputFile="$OUTFILEPDF" \
  140. -c "<</BeginPage{$SCALE $SCALE scale $XTRANS $YTRANS translate}>> setpagedevice" \
  141. -f "$INFILEPDF"
  142. return $?
  143. }
  144. # Runs the ghostscript paper resize script
  145. pageResize() {
  146. # Get new paper sizes if not custom paper
  147. isNotCustomPaper && getGSPaperSize "$RESIZE_PAPER_TYPE"
  148. vprint " Auto Rotate: $(basename $AUTO_ROTATION)"
  149. # Flip detect
  150. local tmpInverter=""
  151. if [[ $FLIP_DETECTION -eq $TRUE || $FLIP_FORCE -eq $TRUE ]]; then
  152. if [[ $PGWIDTH -gt $PGHEIGHT && $RESIZE_WIDTH -lt $RESIZE_HEIGHT ]] || [[ $FLIP_FORCE -eq $TRUE ]]; then
  153. [[ $FLIP_FORCE -eq $TRUE ]] && vprint " Flip Detect: Forced Mode!" || vprint " Flip Detect: Wrong orientation detected!"
  154. vprint " Inverting Width <-> Height"
  155. tmpInverter=$RESIZE_HEIGHT
  156. RESIZE_HEIGHT=$RESIZE_WIDTH
  157. RESIZE_WIDTH=$tmpInverter
  158. else
  159. vprint " Flip Detect: No change needed"
  160. fi
  161. else
  162. vprint " Flip Detect: Disabled"
  163. fi
  164. vprint " Run Resizing: $(uppercase "$RESIZE_PAPER_TYPE") ( "$RESIZE_WIDTH" x "$RESIZE_HEIGHT" ) pts"
  165. # Change page size
  166. "$GSBIN" \
  167. -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dSAFER \
  168. -dCompatibilityLevel="1.5" -dPDFSETTINGS="/printer" \
  169. -dColorConversionStrategy=/LeaveColorUnchanged \
  170. -dSubsetFonts=true -dEmbedAllFonts=true \
  171. -dDEVICEWIDTHPOINTS=$RESIZE_WIDTH -dDEVICEHEIGHTPOINTS=$RESIZE_HEIGHT \
  172. -dAutoRotatePages=$AUTO_ROTATION \
  173. -dFIXEDMEDIA -dPDFFitPage \
  174. -sOutputFile="$OUTFILEPDF" \
  175. -f "$INFILEPDF"
  176. return $?
  177. }
  178. ########################## INITIALIZERS #########################
  179. # Loads external dependencies and checks for errors
  180. initDeps() {
  181. GSBIN="$(which gs 2>/dev/null)"
  182. BCBIN="$(which bc 2>/dev/null)"
  183. IDBIN=$(which identify 2>/dev/null)
  184. MDLSBIN="$(which mdls 2>/dev/null)"
  185. PDFINFOBIN="$(which pdfinfo 2>/dev/null)"
  186. vprint "Checking for ghostscript and bcmath"
  187. if notIsAvailable "$GSBIN"; then printDependency 'ghostscript'; fi
  188. if notIsAvailable "$BCBIN"; then printDependency 'bc'; fi
  189. }
  190. # Checks for dependencies errors, run after getting options
  191. checkDeps() {
  192. if [[ $MODE = "IDENTIFY" ]]; then
  193. vprint "Checking for imagemagick's identify"
  194. if notIsAvailable "$IDBIN"; then printDependency 'imagemagick'; fi
  195. fi
  196. if [[ $MODE = "PDFINFO" ]]; then
  197. vprint "Checking for pdfinfo"
  198. if notIsAvailable "$PDFINFOBIN"; then printDependency 'pdfinfo'; fi
  199. fi
  200. if [[ $MODE = "MDLS" ]]; then
  201. vprint "Checking for MacOS mdls"
  202. if notIsAvailable "$MDLSBIN"; then
  203. initError 'mdls executable was not found! Is this even MacOS?' $EXIT_MAC_MDLS_NOT_FOUND 'nobanner'
  204. fi
  205. fi
  206. }
  207. ######################### CLI OPTIONS ##########################
  208. # Parse options
  209. getOptions() {
  210. while getopts ":vhVis:m:r:pf:a:" o; do
  211. case "${o}" in
  212. v)
  213. ((VERBOSE++))
  214. ;;
  215. h)
  216. printHelp
  217. exit $EXIT_SUCCESS
  218. ;;
  219. V)
  220. printVersion
  221. exit $EXIT_SUCCESS
  222. ;;
  223. i)
  224. JUST_IDENTIFY=$TRUE
  225. ;;
  226. s)
  227. parseScale ${OPTARG}
  228. ;;
  229. m)
  230. parseMode ${OPTARG}
  231. ;;
  232. r)
  233. parsePaperResize ${OPTARG}
  234. ;;
  235. p)
  236. printPaperInfo
  237. exit $EXIT_SUCCESS
  238. ;;
  239. f)
  240. parseFlipDetectionMode ${OPTARG}
  241. ;;
  242. a)
  243. parseAutoRotationMode ${OPTARG}
  244. ;;
  245. *)
  246. initError "Invalid Option: -$OPTARG" $EXIT_INVALID_OPTION
  247. ;;
  248. esac
  249. done
  250. shift $((OPTIND-1))
  251. if [[ $JUST_IDENTIFY -eq $TRUE ]]; then
  252. VERBOSE=0
  253. fi
  254. # Validate input PDF file
  255. INFILEPDF="$1"
  256. isEmpty "$INFILEPDF" && initError "Input file is empty!" $EXIT_NO_INPUT_FILE
  257. isPDF "$INFILEPDF" || initError "Input file is not a PDF file: $INFILEPDF" $EXIT_INPUT_NOT_PDF
  258. isFile "$INFILEPDF" || initError "Input file not found: $INFILEPDF" $EXIT_FILE_NOT_FOUND
  259. printVersion 1 'verbose'
  260. if isMixedMode; then
  261. vprint " Mixed Tasks: Resize & Scale"
  262. isEmpty "$2" && OUTFILEPDF="${INFILEPDF%.pdf}.$(uppercase $RESIZE_PAPER_TYPE).SCALED.pdf"
  263. elif isResizeMode; then
  264. vprint " Single Task: Resize PDF Paper"
  265. isEmpty "$2" && OUTFILEPDF="${INFILEPDF%.pdf}.$(uppercase $RESIZE_PAPER_TYPE).pdf"
  266. else
  267. vprint " Single Task: Scale PDF Contents"
  268. isEmpty "$2" && OUTFILEPDF="${INFILEPDF%.pdf}.SCALED.pdf"
  269. fi
  270. isNotEmpty "$2" && OUTFILEPDF="${2%.pdf}.pdf"
  271. }
  272. # Parses and validates the scaling factor
  273. parseScale() {
  274. AUTOMATIC_SCALING=$FALSE
  275. if ! isFloatBiggerThanZero "$1"; then
  276. printError "Invalid factor: $1"
  277. printError "The factor must be a floating point number greater than 0"
  278. printError "Example: for 80% use 0.8"
  279. exit $EXIT_INVALID_SCALE
  280. fi
  281. SCALE="$1"
  282. }
  283. # Parse a forced mode of operation
  284. parseMode() {
  285. local param="$(lowercase $1)"
  286. case "${param}" in
  287. c|catgrep|'cat+grep')
  288. ADAPTIVEMODE=$FALSE
  289. MODE="CATGREP"
  290. return $TRUE
  291. ;;
  292. i|imagemagick|identify)
  293. ADAPTIVEMODE=$FALSE
  294. MODE="IDENTIFY"
  295. return $TRUE
  296. ;;
  297. m|mdls|quartz|mac)
  298. ADAPTIVEMODE=$FALSE
  299. MODE="MDLS"
  300. return $TRUE
  301. ;;
  302. p|pdfinfo)
  303. ADAPTIVEMODE=$FALSE
  304. MODE="PDFINFO"
  305. return $TRUE
  306. ;;
  307. *)
  308. ADAPTIVEMODE=$TRUE
  309. MODE=""
  310. if [[ "$param" != 'a' && "$param" != 'auto' && "$param" != 'automatic' && "$param" != 'adaptive' ]]; then
  311. printError "Error! Invalid PDF Size Detection Mode: \"$1\", using adaptive mode!"
  312. return $FALSE
  313. fi
  314. return $TRUE
  315. ;;
  316. esac
  317. return $FALSE
  318. }
  319. # Parses and validates the scaling factor
  320. parseFlipDetectionMode() {
  321. local param="$(lowercase $1)"
  322. case "${param}" in
  323. d|disable)
  324. FLIP_DETECTION=$FALSE
  325. FLIP_FORCE=$FALSE
  326. ;;
  327. f|force)
  328. FLIP_DETECTION=$FALSE
  329. FLIP_FORCE=$TRUE
  330. ;;
  331. *)
  332. [[ "$param" != 'a' && "$param" != 'auto' ]] && printError "Error! Invalid Flip Detection Mode: \"$1\", using automatic mode!"
  333. FLIP_DETECTION=$TRUE
  334. FLIP_FORCE=$FALSE
  335. ;;
  336. esac
  337. }
  338. # Parses and validates the scaling factor
  339. parseAutoRotationMode() {
  340. local param="$(lowercase $1)"
  341. case "${param}" in
  342. n|none)
  343. AUTO_ROTATION='/None'
  344. ;;
  345. a|all)
  346. AUTO_ROTATION='/All'
  347. ;;
  348. p|pagebypage|auto)
  349. AUTO_ROTATION='/PageByPage'
  350. ;;
  351. *)
  352. printError "Error! Invalid Auto Rotation Mode: $param, using default: $(basename $AUTO_ROTATION)"
  353. ;;
  354. esac
  355. }
  356. ################### PDF PAGE SIZE DETECTION ####################
  357. ################################################################
  358. # Detects operation mode and also runs the adaptive mode
  359. # PAGESIZE LOGIC
  360. # 1- Try to get Mediabox with CAT/GREP
  361. # 2- MacOS => try to use mdls
  362. # 3- Try to use pdfinfo
  363. # 4- Try to use identify (imagemagick)
  364. # 5- Fail
  365. ################################################################
  366. getPageSize() {
  367. if isNotAdaptiveMode; then
  368. vprint " Get Page Size: Adaptive Disabled"
  369. if [[ $MODE = "CATGREP" ]]; then
  370. vprint " Method: Cat + Grep"
  371. getPageSizeCatGrep
  372. elif [[ $MODE = "MDLS" ]]; then
  373. vprint " Method: Mac Quartz mdls"
  374. getPageSizeMdls
  375. elif [[ $MODE = "PDFINFO" ]]; then
  376. vprint " Method: PDFInfo"
  377. getPageSizePdfInfo
  378. elif [[ $MODE = "IDENTIFY" ]]; then
  379. vprint " Method: ImageMagick's Identify"
  380. getPageSizeImagemagick
  381. else
  382. printError "Error! Invalid Mode: $MODE"
  383. printError "Aborting execution..."
  384. exit $EXIT_INVALID_OPTION
  385. fi
  386. return $TRUE
  387. fi
  388. vprint " Get Page Size: Adaptive Enabled"
  389. vprint " Method: Cat + Grep"
  390. getPageSizeCatGrep
  391. if pageSizeIsInvalid && [[ $OSNAME = "Darwin" ]]; then
  392. vprint " Failed"
  393. vprint " Method: Mac Quartz mdls"
  394. getPageSizeMdls
  395. fi
  396. if pageSizeIsInvalid; then
  397. vprint " Failed"
  398. vprint " Method: PDFInfo"
  399. getPageSizePdfInfo
  400. fi
  401. if pageSizeIsInvalid; then
  402. vprint " Failed"
  403. vprint " Method: ImageMagick's Identify"
  404. getPageSizeImagemagick
  405. fi
  406. if pageSizeIsInvalid; then
  407. vprint " Failed"
  408. printError "Error when detecting PDF paper size!"
  409. printError "All methods of detection failed"
  410. printError "You may want to install pdfinfo or imagemagick"
  411. exit $EXIT_INVALID_PAGE_SIZE_DETECTED
  412. fi
  413. return $TRUE
  414. }
  415. # Gets page size using imagemagick's identify
  416. getPageSizeImagemagick() {
  417. # Sanity and Adaptive together
  418. if notIsFile "$IDBIN" && isNotAdaptiveMode; then
  419. notAdaptiveFailed "Make sure you installed ImageMagick and have identify on your \$PATH" "ImageMagick's Identify"
  420. elif notIsFile "$IDBIN" && isAdaptiveMode; then
  421. return $FALSE
  422. fi
  423. # get data from image magick
  424. local identify="$("$IDBIN" -format '%[fx:w] %[fx:h]BREAKME' "$INFILEPDF" 2>/dev/null)"
  425. if isEmpty "$identify" && isNotAdaptiveMode; then
  426. notAdaptiveFailed "ImageMagicks's Identify returned an empty string!"
  427. elif isEmpty "$identify" && isAdaptiveMode; then
  428. return $FALSE
  429. fi
  430. identify="${identify%%BREAKME*}" # get page size only for 1st page
  431. identify=($identify) # make it an array
  432. PGWIDTH=$(printf '%.0f' "${identify[0]}") # assign
  433. PGHEIGHT=$(printf '%.0f' "${identify[1]}") # assign
  434. return $TRUE
  435. }
  436. # Gets page size using Mac Quarts mdls
  437. getPageSizeMdls() {
  438. # Sanity and Adaptive together
  439. if notIsFile "$MDLSBIN" && isNotAdaptiveMode; then
  440. notAdaptiveFailed "Are you even trying this on a Mac?" "Mac Quartz mdls"
  441. elif notIsFile "$MDLSBIN" && isAdaptiveMode; then
  442. return $FALSE
  443. fi
  444. local identify="$("$MDLSBIN" -mdls -name kMDItemPageHeight -name kMDItemPageWidth "$INFILEPDF" 2>/dev/null)"
  445. if isEmpty "$identify" && isNotAdaptiveMode; then
  446. notAdaptiveFailed "Mac Quartz mdls returned an empty string!"
  447. elif isEmpty "$identify" && isAdaptiveMode; then
  448. return $FALSE
  449. fi
  450. identify=${identify//$'\t'/ } # change tab to space
  451. identify=($identify) # make it an array
  452. if [[ "${identify[5]}" = "(null)" || "${identify[2]}" = "(null)" ]] && isNotAdaptiveMode; then
  453. notAdaptiveFailed "There was no metadata to read from the file! Is Spotlight OFF?"
  454. elif [[ "${identify[5]}" = "(null)" || "${identify[2]}" = "(null)" ]] && isAdaptiveMode; then
  455. return $FALSE
  456. fi
  457. PGWIDTH=$(printf '%.0f' "${identify[5]}") # assign
  458. PGHEIGHT=$(printf '%.0f' "${identify[2]}") # assign
  459. return $TRUE
  460. }
  461. # Gets page size using Linux PdfInfo
  462. getPageSizePdfInfo() {
  463. # Sanity and Adaptive together
  464. if notIsFile "$PDFINFOBIN" && isNotAdaptiveMode; then
  465. notAdaptiveFailed "Do you have pdfinfo installed and available on your \$PATH?" "Linux pdfinfo"
  466. elif notIsFile "$PDFINFOBIN" && isAdaptiveMode; then
  467. return $FALSE
  468. fi
  469. # get data from image magick
  470. local identify="$("$PDFINFOBIN" "$INFILEPDF" 2>/dev/null | grep -i 'Page size:' )"
  471. if isEmpty "$identify" && isNotAdaptiveMode; then
  472. notAdaptiveFailed "Linux PdfInfo returned an empty string!"
  473. elif isEmpty "$identify" && isAdaptiveMode; then
  474. return $FALSE
  475. fi
  476. identify="${identify##*Page size:}" # remove stuff
  477. identify=($identify) # make it an array
  478. PGWIDTH=$(printf '%.0f' "${identify[0]}") # assign
  479. PGHEIGHT=$(printf '%.0f' "${identify[2]}") # assign
  480. return $TRUE
  481. }
  482. # Gets page size using cat and grep
  483. getPageSizeCatGrep() {
  484. # get MediaBox info from PDF file using cat and grep, these are all possible
  485. # /MediaBox [0 0 595 841]
  486. # /MediaBox [ 0 0 595.28 841.89]
  487. # /MediaBox[ 0 0 595.28 841.89 ]
  488. # Get MediaBox data if possible
  489. local mediaBox="$(cat "$INFILEPDF" | grep -a '/MediaBox' | head -n1)"
  490. mediaBox="${mediaBox##*/MediaBox}"
  491. # No page size data available
  492. if isEmpty "$mediaBox" && isNotAdaptiveMode; then
  493. notAdaptiveFailed "There is no MediaBox in the pdf document!"
  494. elif isEmpty "$mediaBox" && isAdaptiveMode; then
  495. return $FALSE
  496. fi
  497. # remove chars [ and ]
  498. mediaBox="${mediaBox//[}"
  499. mediaBox="${mediaBox//]}"
  500. mediaBox=($mediaBox) # make it an array
  501. mbCount=${#mediaBox[@]} # array size
  502. # sanity
  503. if [[ $mbCount -lt 4 ]]; then
  504. printError "Error when reading the page size!"
  505. printError "The page size information is invalid!"
  506. exit $EXIT_INVALID_PAGE_SIZE_DETECTED
  507. fi
  508. # we are done
  509. PGWIDTH=$(printf '%.0f' "${mediaBox[2]}") # Get Round Width
  510. PGHEIGHT=$(printf '%.0f' "${mediaBox[3]}") # Get Round Height
  511. return $TRUE
  512. }
  513. # Prints error message and exits execution
  514. notAdaptiveFailed() {
  515. local errProgram="$2"
  516. local errStr="$1"
  517. if isEmpty "$2"; then
  518. printError "Error when reading input file!"
  519. printError "Could not determine the page size!"
  520. else
  521. printError "Error! $2 was not found!"
  522. fi
  523. isNotEmpty "$errStr" && printError "$errStr"
  524. printError "Aborting! You may want to try the adaptive mode."
  525. exit $EXIT_INVALID_PAGE_SIZE_DETECTED
  526. }
  527. # Verbose print of the Width and Height (Source or New) to screen
  528. vPrintPageSizes() {
  529. vprint " $1 Width: $PGWIDTH postscript-points"
  530. vprint "$1 Height: $PGHEIGHT postscript-points"
  531. }
  532. #################### GHOSTSCRIPT PAPER INFO ####################
  533. # Loads GS paper info to memory
  534. getPaperInfo() {
  535. # name inchesW inchesH mmW mmH pointsW pointsH
  536. sizesUS="\
  537. 11x17 11.0 17.0 279 432 792 1224
  538. ledger 17.0 11.0 432 279 1224 792
  539. legal 8.5 14.0 216 356 612 1008
  540. letter 8.5 11.0 216 279 612 792
  541. lettersmall 8.5 11.0 216 279 612 792
  542. archE 36.0 48.0 914 1219 2592 3456
  543. archD 24.0 36.0 610 914 1728 2592
  544. archC 18.0 24.0 457 610 1296 1728
  545. archB 12.0 18.0 305 457 864 1296
  546. archA 9.0 12.0 229 305 648 864"
  547. sizesISO="\
  548. a0 33.1 46.8 841 1189 2384 3370
  549. a1 23.4 33.1 594 841 1684 2384
  550. a2 16.5 23.4 420 594 1191 1684
  551. a3 11.7 16.5 297 420 842 1191
  552. a4 8.3 11.7 210 297 595 842
  553. a4small 8.3 11.7 210 297 595 842
  554. a5 5.8 8.3 148 210 420 595
  555. a6 4.1 5.8 105 148 297 420
  556. a7 2.9 4.1 74 105 210 297
  557. a8 2.1 2.9 52 74 148 210
  558. a9 1.5 2.1 37 52 105 148
  559. a10 1.0 1.5 26 37 73 105
  560. isob0 39.4 55.7 1000 1414 2835 4008
  561. isob1 27.8 39.4 707 1000 2004 2835
  562. isob2 19.7 27.8 500 707 1417 2004
  563. isob3 13.9 19.7 353 500 1001 1417
  564. isob4 9.8 13.9 250 353 709 1001
  565. isob5 6.9 9.8 176 250 499 709
  566. isob6 4.9 6.9 125 176 354 499
  567. c0 36.1 51.1 917 1297 2599 3677
  568. c1 25.5 36.1 648 917 1837 2599
  569. c2 18.0 25.5 458 648 1298 1837
  570. c3 12.8 18.0 324 458 918 1298
  571. c4 9.0 12.8 229 324 649 918
  572. c5 6.4 9.0 162 229 459 649
  573. c6 4.5 6.4 114 162 323 459"
  574. sizesJIS="\
  575. jisb0 NA NA 1030 1456 2920 4127
  576. jisb1 NA NA 728 1030 2064 2920
  577. jisb2 NA NA 515 728 1460 2064
  578. jisb3 NA NA 364 515 1032 1460
  579. jisb4 NA NA 257 364 729 1032
  580. jisb5 NA NA 182 257 516 729
  581. jisb6 NA NA 128 182 363 516"
  582. sizesOther="\
  583. flsa 8.5 13.0 216 330 612 936
  584. flse 8.5 13.0 216 330 612 936
  585. halfletter 5.5 8.5 140 216 396 612
  586. hagaki 3.9 5.8 100 148 283 420"
  587. sizesAll="\
  588. $sizesUS
  589. $sizesISO
  590. $sizesJIS
  591. $sizesOther"
  592. }
  593. # Gets a paper size in points and sets it to RESIZE_WIDTH and RESIZE_HEIGHT
  594. getGSPaperSize() {
  595. isEmpty "$sizesall" && getPaperInfo
  596. while read l; do
  597. local cols=($l)
  598. if [[ "$1" == ${cols[0]} ]]; then
  599. RESIZE_WIDTH=${cols[5]}
  600. RESIZE_HEIGHT=${cols[6]}
  601. return $TRUE
  602. fi
  603. done <<< "$sizesAll"
  604. }
  605. # Loads an array with paper names to memory
  606. getPaperNames() {
  607. paperNames=(a0 a1 a2 a3 a4 a4small a5 a6 a7 a8 a9 a10 isob0 isob1 isob2 isob3 isob4 isob5 isob6 c0 c1 c2 c3 c4 c5 c6 \
  608. 11x17 ledger legal letter lettersmall archE archD archC archB archA \
  609. jisb0 jisb1 jisb2 jisb3 jisb4 jisb5 jisb6 \
  610. flsa flse halfletter hagaki)
  611. }
  612. # Prints uppercase paper names to screen (used in help)
  613. printPaperNames() {
  614. isEmpty "$paperNames" && getPaperNames
  615. for i in "${!paperNames[@]}"; do
  616. [[ $i -eq 0 ]] && echo -n -e ' '
  617. [[ $i -ne 0 && $((i % 5)) -eq 0 ]] && echo -n -e $'\n '
  618. ppN="$(uppercase ${paperNames[i]})"
  619. printf "%-14s" "$ppN"
  620. done
  621. echo ""
  622. }
  623. # Returns $TRUE if $! is a valid paper name, $FALSE otherwise
  624. isPaperName() {
  625. isEmpty "$1" && return $FALSE
  626. isEmpty "$paperNames" && getPaperNames
  627. for i in "${paperNames[@]}"; do
  628. [[ "$i" = "$1" ]] && return $TRUE
  629. done
  630. return $FALSE
  631. }
  632. # Prints all tables with ghostscript paper information
  633. printPaperInfo() {
  634. printVersion
  635. echo $'\n'"Valid Ghostscript Paper Sizes accepted"$'\n'
  636. getPaperInfo
  637. printPaperTable "ISO STANDARD" "$sizesISO"; echo
  638. printPaperTable "US STANDARD" "$sizesUS"; echo
  639. printPaperTable "JIS STANDARD *Aproximated Points" "$sizesJIS"; echo
  640. printPaperTable "OTHERS" "$sizesOther"; echo
  641. }
  642. # GS paper table helper, prints a full line
  643. printTableLine() {
  644. echo '+-----------------------------------------------------------------+'
  645. }
  646. # GS paper table helper, prints a line with dividers
  647. printTableDivider() {
  648. echo '+-----------------+-------+-------+-------+-------+-------+-------+'
  649. }
  650. # GS paper table helper, prints a table header
  651. printTableHeader() {
  652. echo '| Name | inchW | inchH | mm W | mm H | pts W | pts H |'
  653. }
  654. # GS paper table helper, prints a table title
  655. printTableTitle() {
  656. printf "| %-64s%s\n" "$1" '|'
  657. }
  658. # GS paper table printer, prints a table for a paper variable
  659. printPaperTable() {
  660. printTableLine
  661. printTableTitle "$1"
  662. printTableLine
  663. printTableHeader
  664. printTableDivider
  665. while read l; do
  666. local cols=($l)
  667. printf "| %-15s | %+5s | %+5s | %+5s | %+5s | %+5s | %+5s |\n" ${cols[*]};
  668. done <<< "$2"
  669. printTableDivider
  670. }
  671. # Validades the a paper resize CLI option and sets the paper to $RESIZE_PAPER_TYPE
  672. parsePaperResize() {
  673. isEmpty "$1" && initError 'Invalid Paper Type: (empty)' $EXIT_INVALID_PAPER_SIZE
  674. local lowercasePaper="$(lowercase $1)"
  675. if [[ "$1" = 'custom' ]]; then
  676. if isNotValidMeasure "$2" || ! isFloatBiggerThanZero "$3" || ! isFloatBiggerThanZero "$4"; then
  677. initError "Invalid Custom Paper Definition!"$'\n'"Use: -r 'custom <measurement> <width> <height>'"$'\n'"Measurements: mm, in, pts" $EXIT_INVALID_OPTION
  678. fi
  679. RESIZE_PAPER_TYPE="custom"
  680. CUSTOM_RESIZE_PAPER=$TRUE
  681. if isMilimeter "$2"; then
  682. RESIZE_WIDTH="$(milimetersToPoints "$3")"
  683. RESIZE_HEIGHT="$(milimetersToPoints "$4")"
  684. elif isInch "$2"; then
  685. RESIZE_WIDTH="$(inchesToPoints "$3")"
  686. RESIZE_HEIGHT="$(inchesToPoints "$4")"
  687. elif isPoint "$2"; then
  688. RESIZE_WIDTH="$3"
  689. RESIZE_HEIGHT="$4"
  690. else
  691. initError "Invalid Custom Paper Definition!"$'\n'"Use: -r 'custom <measurement> <width> <height>'"$'\n'"Measurements: mm, in, pts" $EXIT_INVALID_OPTION
  692. fi
  693. else
  694. isPaperName "$lowercasePaper" || initError "Invalid Paper Type: $1" $EXIT_INVALID_PAPER_SIZE
  695. RESIZE_PAPER_TYPE="$lowercasePaper"
  696. fi
  697. }
  698. # Returns $TRUE if $1 is a valid measurement for a custom paper, $FALSE otherwise
  699. isNotValidMeasure() {
  700. isMilimeter "$1" || isInch "$1" || isPoint "$1" && return $FALSE
  701. return $TRUE
  702. }
  703. # Returns $TRUE if $1 is a valid milimeter string, $FALSE otherwise
  704. isMilimeter() {
  705. [[ "$1" = 'mm' || "$1" = 'milimeters' || "$1" = 'milimeter' ]] && return $TRUE
  706. return $FALSE
  707. }
  708. # Returns $TRUE if $1 is a valid inch string, $FALSE otherwise
  709. isInch() {
  710. [[ "$1" = 'in' || "$1" = 'inch' || "$1" = 'inches' ]] && return $TRUE
  711. return $FALSE
  712. }
  713. # Returns $TRUE if $1 is a valid point string, $FALSE otherwise
  714. isPoint() {
  715. [[ "$1" = 'pt' || "$1" = 'pts' || "$1" = 'point' || "$1" = 'points' ]] && return $TRUE
  716. return $FALSE
  717. }
  718. # Returns $TRUE if a custom paper is being used, $FALSE otherwise
  719. isCustomPaper() {
  720. return $CUSTOM_RESIZE_PAPER
  721. }
  722. isNotCustomPaper() {
  723. isCustomPaper && return $FALSE
  724. return $TRUE
  725. }
  726. # Returns $TRUE if the scale was set manually, $FALSE if we are using automatic scaling
  727. isManualScaledMode() {
  728. [[ $AUTOMATIC_SCALING -eq $TRUE ]] && return $FALSE
  729. return $TRUE
  730. }
  731. # Returns true if we are resizing a paper (ignores scaling), false otherwise
  732. isResizeMode() {
  733. isEmpty $RESIZE_PAPER_TYPE && return $FALSE
  734. return $TRUE
  735. }
  736. # Returns true if we are resizing a paper and the scale was manually set
  737. isMixedMode() {
  738. isResizeMode && isManualScaledMode && return $TRUE
  739. return $FALSE
  740. }
  741. # Prints the lowercase char value for $1
  742. lowercaseChar() {
  743. case "$1" in
  744. [A-Z])
  745. n=$(printf "%d" "'$1")
  746. n=$((n+32))
  747. printf \\$(printf "%o" "$n")
  748. ;;
  749. *)
  750. printf "%s" "$1"
  751. ;;
  752. esac
  753. }
  754. # Prints the lowercase version of a string
  755. lowercase() {
  756. word="$@"
  757. for((i=0;i<${#word};i++))
  758. do
  759. ch="${word:$i:1}"
  760. lowercaseChar "$ch"
  761. done
  762. }
  763. # Prints the uppercase char value for $1
  764. uppercaseChar(){
  765. case "$1" in
  766. [a-z])
  767. n=$(printf "%d" "'$1")
  768. n=$((n-32))
  769. printf \\$(printf "%o" "$n")
  770. ;;
  771. *)
  772. printf "%s" "$1"
  773. ;;
  774. esac
  775. }
  776. # Prints the uppercase version of a string
  777. uppercase() {
  778. word="$@"
  779. for((i=0;i<${#word};i++))
  780. do
  781. ch="${word:$i:1}"
  782. uppercaseChar "$ch"
  783. done
  784. }
  785. # Prints the postscript points rounded equivalent from $1 mm
  786. milimetersToPoints() {
  787. local pts=$(echo "scale=8; $1 * 72 / 25.4" | "$BCBIN")
  788. printf '%.0f' "$pts" # Print rounded conversion
  789. }
  790. # Prints the postscript points rounded equivalent from $1 inches
  791. inchesToPoints() {
  792. local pts=$(echo "scale=8; $1 * 72" | "$BCBIN")
  793. printf '%.0f' "$pts" # Print rounded conversion
  794. }
  795. # Prints the mm equivalent from $1 postscript points
  796. pointsToMilimeters() {
  797. local pts=$(echo "scale=8; $1 / 72 * 25.4" | "$BCBIN")
  798. printf '%.0f' "$pts" # Print rounded conversion
  799. }
  800. # Prints the inches equivalent from $1 postscript points
  801. pointsToInches() {
  802. local pts=$(echo "scale=8; $1 / 72" | "$BCBIN")
  803. printf '%.2f' "$pts" # Print rounded conversion
  804. }
  805. ########################## VALIDATORS ##########################
  806. # Returns $TRUE if $PGWIDTH OR $PGWIDTH are empty or NOT an Integer, $FALSE otherwise
  807. pageSizeIsInvalid() {
  808. if isNotAnInteger "$PGWIDTH" || isNotAnInteger "$PGHEIGHT"; then
  809. return $TRUE
  810. fi
  811. return $FALSE
  812. }
  813. # Return $TRUE if adaptive mode is enabled, $FALSE otherwise
  814. isAdaptiveMode() {
  815. return $ADAPTIVEMODE
  816. }
  817. # Return $TRUE if adaptive mode is disabled, $FALSE otherwise
  818. isNotAdaptiveMode() {
  819. isAdaptiveMode && return $FALSE
  820. return $TRUE
  821. }
  822. # Return $TRUE if $1 is empty, $FALSE otherwise
  823. isEmpty() {
  824. [[ -z "$1" ]] && return $TRUE
  825. return $FALSE
  826. }
  827. # Return $TRUE if $1 is NOT empty, $FALSE otherwise
  828. isNotEmpty() {
  829. [[ -z "$1" ]] && return $FALSE
  830. return $TRUE
  831. }
  832. # Returns $TRUE if $1 is an integer, $FALSE otherwise
  833. isAnInteger() {
  834. case $1 in
  835. ''|*[!0-9]*) return $FALSE ;;
  836. *) return $TRUE ;;
  837. esac
  838. }
  839. # Returns $TRUE if $1 is NOT an integer, $FALSE otherwise
  840. isNotAnInteger() {
  841. case $1 in
  842. ''|*[!0-9]*) return $TRUE ;;
  843. *) return $FALSE ;;
  844. esac
  845. }
  846. # Returns $TRUE if $1 is a floating point number (or an integer), $FALSE otherwise
  847. isFloat() {
  848. [[ -n "$1" && "$1" =~ ^-?[0-9]*([.][0-9]+)?$ ]] && return $TRUE
  849. return $FALSE
  850. }
  851. # Returns $TRUE if $1 is a floating point number bigger than zero, $FALSE otherwise
  852. isFloatBiggerThanZero() {
  853. isFloat "$1" && [[ (( $1 > 0 )) ]] && return $TRUE
  854. return $FALSE
  855. }
  856. # Returns $TRUE if $1 has a .pdf extension, false otherwsie
  857. isPDF() {
  858. [[ "$1" =~ ^..*\.pdf$ ]] && return $TRUE
  859. return $FALSE
  860. }
  861. # Returns $TRUE if $1 is a file, false otherwsie
  862. isFile() {
  863. [[ -f "$1" ]] && return $TRUE
  864. return $FALSE
  865. }
  866. # Returns $TRUE if $1 is NOT a file, false otherwsie
  867. notIsFile() {
  868. [[ -f "$1" ]] && return $FALSE
  869. return $TRUE
  870. }
  871. # Returns $TRUE if $1 is executable, false otherwsie
  872. isExecutable() {
  873. [[ -x "$1" ]] && return $TRUE
  874. return $FALSE
  875. }
  876. # Returns $TRUE if $1 is NOT executable, false otherwsie
  877. notIsExecutable() {
  878. [[ -x "$1" ]] && return $FALSE
  879. return $TRUE
  880. }
  881. # Returns $TRUE if $1 is a file and executable, false otherwsie
  882. isAvailable() {
  883. if isFile "$1" && isExecutable "$1"; then
  884. return $TRUE
  885. fi
  886. return $FALSE
  887. }
  888. # Returns $TRUE if $1 is NOT a file or NOT executable, false otherwsie
  889. notIsAvailable() {
  890. if notIsFile "$1" || notIsExecutable "$1"; then
  891. return $TRUE
  892. fi
  893. return $FALSE
  894. }
  895. ###################### PRINTING TO SCREEN ######################
  896. # Prints version
  897. printVersion() {
  898. local vStr=""
  899. [[ "$2" = 'verbose' ]] && vStr=" - Verbose Execution"
  900. local strBanner="$PDFSCALE_NAME v$VERSION$vStr"
  901. if [[ $1 -eq 2 ]]; then
  902. printError "$strBanner"
  903. elif [[ $1 -eq 3 ]]; then
  904. local extra="$(isNotEmpty "$2" && echo "$2")"
  905. echo "$strBanner$extra"
  906. else
  907. vprint "$strBanner"
  908. fi
  909. }
  910. # Prints the scale factor to screen, or custom message
  911. vPrintScaleFactor() {
  912. local scaleMsg="$SCALE"
  913. isNotEmpty "$1" && scaleMsg="$1"
  914. vprint " Scale Factor: $scaleMsg"
  915. }
  916. # Prints help info
  917. printHelp() {
  918. printVersion 3
  919. local paperList="$(printPaperNames)"
  920. echo "
  921. Usage: $PDFSCALE_NAME <inFile.pdf>
  922. $PDFSCALE_NAME -i <inFile.pdf>
  923. $PDFSCALE_NAME [-v] [-s <factor>] [-m <page-detection>] <inFile.pdf> [outfile.pdf]
  924. $PDFSCALE_NAME [-v] [-r <paper>] [-f <flip-detection>] [-a <auto-rotation>] <inFile.pdf> [outfile.pdf]
  925. $PDFSCALE_NAME -p
  926. $PDFSCALE_NAME -h
  927. $PDFSCALE_NAME -V
  928. Parameters:
  929. -v Verbose mode, prints extra information
  930. Use twice for timestamp
  931. -h Print this help to screen and exits
  932. -V Prints version to screen and exits
  933. -m <mode> Page size Detection mode
  934. May disable the Adaptive Mode
  935. -i <file> Prints <file> Page Size information to screen and exits
  936. -s <factor> Changes the scaling factor or forces scaling
  937. Defaults: $SCALE / no scaling (resize mode)
  938. MUST be a number bigger than zero
  939. Eg. -s 0.8 for 80% of the original size
  940. -r <paper> Triggers the Resize Paper Mode
  941. Resize PDF paper proportionally
  942. Uses a valid paper name or a custom defined paper
  943. -f <mode> Flip Detection Mode, defaults to 'auto'.
  944. Inverts Width <-> Height of a Resized PDF.
  945. Modes: a, auto - automatic detection, default
  946. f, force - forces flip W <-> H
  947. d, disable - disables flipping
  948. -a <mode> GS Auto-Rotation Setting, defaults to 'PageByPage'.
  949. Setting for GS -dAutoRotatePages.
  950. Modes: p, pagebypage - auto-rotates pages individually
  951. a, all - rotates all pages (or none) depending
  952. on a kind of \"majority decision\"
  953. n, none - retains orientation of each page
  954. -p Prints Ghostscript paper info tables to screen
  955. Scaling Mode:
  956. The default mode of operation is scaling mode with fixed paper
  957. size and scaling pre-set to $SCALE. By not using the resize mode
  958. you are using scaling mode. Flip-Detection and Auto-Rotation are
  959. disabled in Scaling mode.
  960. Resize Paper Mode:
  961. Disables the default scaling factor! ($SCALE)
  962. Changes the PDF Paper Size in points. Will fit-to-page.
  963. Mixed Mode:
  964. In mixed mode both the -s option and -r option must be specified.
  965. The PDF will be first resized then scaled.
  966. Output filename:
  967. The output filename is optional. If no file name is passed
  968. the output file will have the same name/destination of the
  969. input file with added suffixes:
  970. .SCALED.pdf is added to scaled files
  971. .<PAPERSIZE>.pdf is added to resized files
  972. .<PAPERSIZE>.SCALED.pdf is added in mixed mode
  973. Page Size Detection Modes:
  974. a, adaptive Default mode, tries all the methods below
  975. c, cat+grep Forces the use of the cat + grep method
  976. m, mdls Forces the use of MacOS Quartz mdls
  977. p, pdfinfo Forces the use of PDFInfo
  978. i, identify Forces the use of ImageMagick's Identify
  979. Valid Paper Names: (case-insensitive)
  980. $paperList
  981. Custom Paper Size:
  982. Paper size can be set manually in Milimeters, Inches or Points.
  983. Use: $PDFSCALE_NAME -r 'custom <measurement> <width> <height>'
  984. Ex: $PDFSCALE_NAME -r 'custom mm 300 300'
  985. Measurements can be: mm, inch, pts.
  986. Custom paper definition MUST be quoted into a single parameter.
  987. Actual size is applied in points (mms and inches are transformed).
  988. Additional Notes:
  989. - Adaptive Page size detection will try different modes until
  990. it gets a page size. You can force a mode with -m 'mode'.
  991. - Options must be passed before the file names to be parsed.
  992. - Having the extension .pdf on the output file name is optional,
  993. it will be added if not present.
  994. - File and folder names with spaces should be quoted or escaped.
  995. - The scaling is centered and using a scale bigger than 1 may
  996. result on cropping parts of the pdf.
  997. - Most of the options are case-insensitive, Ex: -m PdFinFo
  998. Examples:
  999. $PDFSCALE_NAME myPdfFile.pdf
  1000. $PDFSCALE_NAME -i '/home/My Folder/My PDF File.pdf'
  1001. $PDFSCALE_NAME myPdfFile.pdf \"My Scaled Pdf\"
  1002. $PDFSCALE_NAME -v -v myPdfFile.pdf
  1003. $PDFSCALE_NAME -s 0.85 myPdfFile.pdf My\\ Scaled\\ Pdf.pdf
  1004. $PDFSCALE_NAME -m pdfinfo -s 0.80 -v myPdfFile.pdf
  1005. $PDFSCALE_NAME -v -v -m i -s 0.7 myPdfFile.pdf
  1006. $PDFSCALE_NAME -r A4 myPdfFile.pdf
  1007. $PDFSCALE_NAME -v -v -r \"custom mm 252 356\" -s 0.9 -f \"../input file.pdf\" \"../my new pdf\"
  1008. $PDFSCALE_NAME -h
  1009. "
  1010. }
  1011. # Prints usage info
  1012. usage() {
  1013. [[ "$2" != 'nobanner' ]] && printVersion 2
  1014. isNotEmpty "$1" && printError "$1"
  1015. printError "Usage: $PDFSCALE_NAME [-v] [-s <factor>] [-m <mode>] <inFile.pdf> [outfile.pdf]"
  1016. printError "Try: $PDFSCALE_NAME -h # for help"
  1017. }
  1018. # Prints Verbose information
  1019. vprint() {
  1020. [[ $VERBOSE -eq 0 ]] && return $TRUE
  1021. timestamp=""
  1022. [[ $VERBOSE -gt 1 ]] && timestamp="$(date +%Y-%m-%d:%H:%M:%S) | "
  1023. echo "$timestamp$1"
  1024. }
  1025. # Prints dependency information and aborts execution
  1026. printDependency() {
  1027. #printVersion 2
  1028. local brewName="$1"
  1029. [[ "$1" = 'pdfinfo' && "$OSNAME" = "Darwin" ]] && brewName="xpdf"
  1030. printError $'\n'"ERROR! You need to install the package '$1'"$'\n'
  1031. printError "Linux apt-get.: sudo apt-get install $1"
  1032. printError "Linux yum.....: sudo yum install $1"
  1033. printError "MacOS homebrew: brew install $brewName"
  1034. printError $'\n'"Aborting..."
  1035. exit $EXIT_MISSING_DEPENDENCY
  1036. }
  1037. # Prints initialization errors and aborts execution
  1038. initError() {
  1039. local errStr="$1"
  1040. local exitStat=$2
  1041. isEmpty "$exitStat" && exitStat=$EXIT_ERROR
  1042. usage "ERROR! $errStr" "$3"
  1043. exit $exitStat
  1044. }
  1045. # Prints to stderr
  1046. printError() {
  1047. echo >&2 "$@"
  1048. }
  1049. ########################## EXECUTION ###########################
  1050. initDeps
  1051. getOptions "${@}"
  1052. main
  1053. exit $?