Edit:
Important note before reading further: since Kusalananda's anwser, my question is now quite useless, since he pointed out a bug in another script I used. Now this bug is fixed, the below errors I described no longer occur!
There are two issues in your code which causes the value in $extension to be expanded
The second issue is the function itself
TL;DR
I was stuck when I started writing the question, but found a solution that works (using shell noglob), BUT I still have a question of "would it be possible to write".
I'm sure this has already been answered, but I get lost in hundreds of topics about bash expansion.
Here is my case:
- I want to run a script (lets say
ffmpegwith option-pattern_type glob -imode that accepts a regexp like*.JPG) - taking an argument (lets say
*.JPG) - argument coming from a variable (lets say
$extension) - variable coming from script parameters (lets say
$1) - but I do not want shell to expand
$extensionas by default for a pattern like*.JPG
Note that all this actions take place in a script script.sh.
Thus, the user could run:
script.sh 'JPG' ; # where $1='JPG' Note: in script.sh, I concatenate *. and $1 to get a more final regexp like *.JPG
I read (from here https://stackoverflow.com/a/11456496/912046) that shell expansion occurs before ffmpeg receives arguments (ffmpeg even does not know Shell expansion took place)
I tried to play with quotes, double quotes, or backslashes around ${extension} in different ways, unsuccessfully.
Here are some tries:
ffmpeg ... "${extension}" leads to: ffmpeg 1.jpg 2.jpg [...] (expansion occurs)
ffmpeg ... ${extension} same
ffmpeg ... '${extension}' leads to no file match because of searching pattern ${extension} (variable name is used literally)
extension="\'${extension}\'" ; # wrapping the single quotes (preventing expansion) directly in variable ffmpeg ... ${extension} leads to no file match because of searching pattern '*.jpg' (including single quotes)
ffmpeg ... \"${extension}\" same but searching for "*.jpg" (including double quotes)
I finally succeeded using Shell noglob option.
Here is the command for curious:
set -f ; # disable glob (prevent expansion on '*.jpg') ffmpeg -pattern_type glob -i ${extension} movie.mp4 ; set +f ; # restore, but what if glob was already disabled? I should not restore it then? But for my curiosity, is there another way of preventing expansion on a script argument coming from a variable we WANT to be resolved? (thus, the way I know of preventing expansion (using single quotes) makes variable no longer resolved/replaced).
Something like : (but I read string concatenation should be avoided for safety, injection)
ffmpeg '${extension}' || | 3 || 2 | 1 where :
- 1: would open single quote for final result being
ffmpeg '*.jpg' - 2: would inject and resolve our variable
extensionto.jpg - 3: would close single quote for
ffmpegto receive argument as if I manually had written'*.jpg'
Edit: after comment about how extension variable is assigned:
local extension="${2}" ; echo $extension ; extension="${extension:=jpg}" ; # Default on "jpg" extension # wrapp extension type in single quotes + prefix with "*." extension="*.${extension}" ; Then, using it with:
runprintcommand ffmpeg -loglevel verbose -pattern_type glob -i ${extension} "$movieName" ; Where the runprintcommand function/script being:
function runprintcommand() { echo "Command to run: (Note: '\\' escape character may not be printed)" ; echo "$*" ; $* ; }
"$extension"(or"${extension}") would expand the variable, but would under no circumstances perform filename globbing on the result, unless you usedevalon the result of the expansion. You are doing something very strange if it did that. Or,ffmpegmight possibly do its own globbing, which it would do regardless ofset -fin that case. Show us how you assign toextensionto create it from$1.ffmpegto a custom homemade, possibly brokenrunprintcommandfunction, which may interfer with globbing.extensionvariable's value.