Recursively convert all JPGs into one PDF in each folder using img2pdf

bashcommand lineconversionpdfwindows-subsystem-for-linux

I have three levels of folders like main, sub-1 and sub-2. my main folder has lot of sub-1 folders and sub-1 has lot of sub-2 folder with JPG images inside.

I copy JPG files from sub-2 to its parent sub-1 folder FROM main folder by using this command.

find . -type f -name "*.jpg" -exec sh -c 'for p; do
  cp "$p" "${p%/*/*}"
done' _ {} +

Now I have to convert all jpgs into one pdf file inside each sub-1 folder from my MAIN folder, so there will be my all copied jpgs along with converted pdf in sub-1 (pdf name should be the folder name ex: sub-1). after convert finished I have to delete the copied jpgs only inside sub-1 folder (not original jpgs), so there will be many sub-2 folders with a single pdf file.

I am using img2pdf library to covert my images. and I tried this command below it does not do the work, I could not find any solution. Now how do I make this works?

find . -name '*.jpg' -type f -exec bash -c 'img2pdf *.jpg -o "${PWD##*/}".pdf' {} + \

Best Answer

I did some tests in my Photos directory tree, and the following system with two shellscripts works for me.

first:

#!/bin/bash

find * -type d -exec second {} \;
echo ""

second:

#!/bin/bash

num=$(ls "$1"/*.jpg 2> /dev/null | wc -l)
if [ $num -ne 0 ]
then
 echo -n "."
 img2pdf -o "$1/${1//\//-}_${num}_pictures".pdf "$1"/*.jpg
fi

Edit twice: Alternate script second makes a pdf file without number of pictures and 'pictures' in the name:

#!/bin/bash

num=$(ls "$1"/*.jpg 2> /dev/null | wc -l)
if [ $num -ne 0 ]
then
 echo -n "."
 img2pdf -o "$1/${1##*/}".pdf "$1"/*.jpg
fi
  • Copy and paste from the code areas into a text editor and create the files first and second

  • Make them executable

    chmod +x first second
    
  • move them to a directory in PATH. If this is only for your personal use, [create and] move them in into ~/bin. Otherwise if other users should also use these shellscripts, move them into /usr/local/bin

    mkdir ~/bin
    mv first second ~/bin
    

    You may need to reboot to get ~/bin into your PATH.

Now you are ready to use them. Change directory to the top or the directory tree, where you have your pictures and run first.

Example (but you have local names, not Pictures like the English),

cd ~/Pictures
first

It will write a dot to the terminal window for each subdirectory where it finds at least one picture and creates a pdf file.

The you can find the pdf files with the following command

find -name "*.pdf"

Major edit:

After a discussion with the original poster, I think I understood the structure of the directory tree to be processed. Copies of the files at lower levels are located in the sub-1 directories with person's names. The files in these sub-1 directories are to be merged into pdf-files.

Example:

$ tree -U
.
├── adam
│   ├── mkusb-minp-2-crop.jpg
│   ├── us_keyboard_for_sudo_password.jpg
│   ├── nautilus-connect-to-server-2.jpg
│   ├── pict1
│   │   ├── mkusb-minp-2-crop.jpg
│   │   └── nautilus-connect-to-server-2.jpg
│   ├── pict2
│   │   └── us_keyboard_for_sudo_password.jpg
│   └── adam.pdf
└── betty
    ├── nautilus-connect-to-server-1.jpg
    ├── mkusb-minp-3-cropx.jpg
    ├── pict1
    │   ├── nautilus-connect-to-server-1.jpg
    │   └── calamares-mount-failed.jpg
    ├── pict2
    │   └── mkusb-minp-3-cropx.jpg
    ├── calamares-mount-failed.jpg
    └── betty.pdf

6 directories, 14 files

If you change working directory with cd to where these name-directories are located, you can use the following modified first shellscript.

#!/bin/bash

find -mindepth 1 -maxdepth 1 -type d -exec second {} \;
echo ""

It will run the second shellscript only in the name-directories and not look for what is in [upper or] lower levels of the directory tree.

The following shows how find finds only the name-directories

$ find -mindepth 1 -maxdepth 1
./adam
./betty