Search code examples
bashprintfquoting

Create dynamic options menu with kdialog bash script : Printf can't do the job ? quoting issue


i would like create a menu with kdialog like this

  kdialog --menu "choose your profile"  "\"-vcodec mpeg2\"" "mpeg" 
  "\"vcodec stuff -ab 100ak\"" "avi" "\"-acodec mp3 -ab 128k"\" "mp3"

now

array a contains options array b contains name of a profile

it seems kdialog has some problem with "-ab" generally it seemes it takes -stuff like an option so it needs to be "\"-vcodec mpeg2\"".

basically my problem is a quoting problem , i have used printf but i can't get it

this is my code:

a=(-vcodec mp3 -ab 128k, -vcodec mpeg2video -b 1200k -ab 128k -acodec mp3 -r 25 -ar 44100 ) ; b=(mp3, mpg) ; eval kdialog --menu "choose your profile" $(for ((i = 0; i <=$(( ${#a[@]} -1 )) ; i++ )) ; do printf "\\'%s\\' %s " "${a[i]}" "${b[i]}" ; done)

solution

file to read $HOME/FFmpeg_profiles.lst

mpeg  -vcodec mpeg2 -ab 1000k 
avi  -vcodec avi -ab 1000k   
mp3 -acodec mp3 -ab 128k

script i did

function_load_profiles(){
k=0
while read line; do 

nameprofile[$k]="$(echo "$line" | awk '{print $1}')"
ffmpegoptionprofile[$k]="$(echo "$line" | awk '{ for(b=2; b<=NF; b++) {printf("%s ", $b)} } ' )"


 k=$(( $k+1 ))
done < "$HOME/FFmpeg_profiles.lst"

}

function_load_profiles 

ARGS="--menu \"choose your profile\" --"
for ((i=0; i<${#nameprofile[@]}; i++)); do
    ARGS="$ARGS \"${ffmpegoptionprofile[$i]}\" \"${nameprofile[$i]}\""
done

SELECTED_OPTIONS=$(echo $ARGS | xargs kdialog)
echo $SELECTED_OPTIONS

Solution

  • #!/bin/bash
    A=("-vcodec mp3 -ab 128k"  
       "-vcodec mpeg2video -b 1200k -ab 128k -acodec mp3 -r 25 -ar 44100")
    B=("mp3" "mpg")
    
    # Build command line args
    ARGS="--menu \"choose your profile\" --"
    for ((i=0; i<${#A[@]}; i++)); do
        ARGS="$ARGS \"${A[$i]}\" \"${B[$i]}\""
    done
    
    SELECTED_OPTIONS=$(echo $ARGS | xargs kdialog)
    echo $SELECTED_OPTIONS
    

    We use xargs to overcome the issue of the quoted options (with spaces) being treated as multiple args instead of a single argument, i.e. "kdialog $ARGS" won't work as expected.

    xargs is preferable to "eval kdialog $ARGS" as it can avoid command injection.


    Updates

    Based on your updated example where you're actually loading the values form a text file, you can do the same without the intermediate arrays:

    #!/bin/bash
    PROFILE_FILE="FFmpeg_profiles.lst"
    ARGS="--menu \"choose your profile\" --"
    
    while read PROFILE OPTS; do
        ARGS="${ARGS} \"${OPTS}\" \"${PROFILE}\""
    done < $PROFILE_FILE
    
    echo $ARGS | xargs kdialog