0

I'm trying to make a function that will make my life easier converting images to pdf. I'm using img2pdf which is a Python script. I want to be able to pass files and directory to my function (with wild mark for expansion like: directory/*).

I come to a point where I fix the issues with Windows path conversion, but then realize now the function doesn't work if the path has spaces, or it comes to a point where Python will just error on pathing.

I tried writing the function, making a string that contains all the files:

imgtopdf(){
    list=""
    while [[ "$1" != "" ]] ; do
        list+=" '$(cygpath -w "$1")'" # Tried $(echo "$list" | xargs -0 echo) but it removes back-slashes!
        shift
    done
    list="${list:1}"
    echo $list
    img2pdf -o img2pdf.pdf --pagesize A4 $list
}

Then tried using an array to hold all the files:

imgtopdf(){
    list=()
    while [[ "$1" != "" ]] ; do
        list+="$(cygpath -w "$1")"
        shift
    done
    echo ${list[@]}
    img2pdf -o img2pdf.pdf --pagesize A4 ${list[*]}
}

Note: cygpath -w is responsible for converting a /cygdrive/ path to Windows path, so that Python understands the pathing.

Shayan
  • 709
  • 1
  • 15
  • 31
  • please update the question with 1) an example invocation of the `imgtopdf` function (plus some typical args), 2) the expected structure of the `list` array, 3) the resulting call to `img2pdf` and 4) the output from `echo $list` – markp-fuso May 06 '21 at 01:02
  • there are several tools in cygwin to convert images. GraphicsMagick and ImageMagick are some. No reason to use `cygpath -w` when passing filles to cygwin programs. – matzeri May 06 '21 at 04:19

1 Answers1

2

Quoting is crucial: use "${list[@]}", not ${list[*]}. At the risk of self-serving, see https://stackoverflow.com/a/12316565/7552

Also, the syntax to append an element to an array requires parentheses (the extra spaces are optional):

list+=( "$(cygpath -w "$1")" )

The best way in bash to inspect a variable is with declare -p list

imgtopdf() {
    list=()
    for file in "$@"; do
        list+=( "$(cygpath -w "$file")" )
    done
    declare -p list
    img2pdf -o img2pdf.pdf --pagesize A4 "${list[@]}"
}
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • As add-on a classical reading on the matter :https://www.grymoire.com/Unix/Quote.html – matzeri May 06 '21 at 04:25
  • That answer you linked me is brilliant! I had read about $@ and $* differences on a lot of websites before but never quite understood the difference. Thanks so much. And from my understanding, there's no way to do this with one full string. We have to use Arrays. Please correct me if I'm wrong. – Shayan May 06 '21 at 08:01
  • 1
    Correct. See [I'm trying to put a command in a variable, but the complex cases always fail!](http://mywiki.wooledge.org/BashFAQ/050) – glenn jackman May 06 '21 at 11:08