How to pass * as part of argument string to script?

Bo Berglund bo.berglund at gmail.com
Wed Aug 25 08:22:57 UTC 2021


On Wed, 25 Aug 2021 09:00:03 +0100, Chris Green <cl at isbd.net> wrote:

>On Wed, Aug 25, 2021 at 09:24:37AM +0200, Bo Berglund wrote:
>> I am writing a script to prune a directory of certain files and it works fine
>> provided the pattern to search for is entered directly in the script.
>> But when I try to set it as a parameter on the command line the pattern seems to
>> be expanded before being read by the script...
>> How can I avoid this?
>> 
>> Here is how I read the template argument:
>> 
>> if [ -z "$2" ]; then
>>   template="202*.mp4" #Default file template for listing
>> else
>>   template="$2"
>> fi
>> 
>> And here is how template is used:
>> cntall=`find . -maxdepth 1 -name "202*.mp4" -printf '.' | wc -m`
>> #cntall=`find . -maxdepth 1 -name "${template}" -printf '.' | wc -m`
>> 
>> As shown it works OK using the first line.
>> 
>> But if I move the comment to the line above and enter the string 202*.mp4 as
>> argument 2 on the command line then the script is no longer working.
>> 
>> It turns out that $template is set to the first file name *matching* the pattern
>> with the entered wildcard *!
>> 
>> So if I have these files:
>> 2021-08-12_myvideo.mp4
>> 2021-08-13_myvideo.mp4
>> 2021-08-14_myvideo.mp4
>> 2021-08-15_myvideo.mp4
>> 2021-08-16_myvideo.mp4
>> 2021-08-17_myvideo.mp4
>> 
>> I expect cntall to be set to 6 but in fact it will be 1 because inside the
>> script the entered string 202*.mp4 intended as $template is expanded to be
>> 2021-08-12_myvideo.mp4, which when used as $template always will return 1 from
>> the call above...
>> 
>> How can I use a template input with the script without Ubuntu expanding my input
>> before it gets to the script?
>> 
>By changing the quoting!  :-)
>
>You probably need a line something like:-
>
>    template='202*.mp4' #Default file template for listing
>
>Otherwise, as you have found out, bash expands the *s there.  Bash
>expands variables, *, etc. within " but not within '.

Well the problem is not the *default* template because that works fine.
If I make the call:
prunelist
it use a max count of 5 thanks to this, which I did not show:

if [ -z "$1" ]; then
  cnt="5" #Leave at least 5 files in place with no argument
else
  cnt=$1
fi

and the default template is then set by:

if [ -z "$2" ]; then
  template="202*.mp4" #Default file template for listing
else
  template="$2"
fi

but if I call the script as follows:

prunevideos 3 202*.mp4

then $template inside the script becomes 2021-08-12_myvideo.mp4 and only one
match is found.

Do you mean that there is no way I can transfer a * character into a script as
part of an argument? 

For completeness here is the current (debug) state of the prunelist scrip, which
is called from the prunevideos script expecting a list of videos to remove:

#!/bin/bash
# List excess files to remove, leaving the number in the call argument in place
# Check target file argument
if [ -z "$1" ]; then
  cnt="5" #Leave at least 5 files in place with no argument
else
  cnt=$1
fi

if [ $cnt -lt "0" ]; then #Do not allow negative arguments
#  echo "Negative file count not allowed!"
#  echo " Usage: $0 [count [template]]"
  exit
fi

if [ -z "$2" ]; then
  template="202*.mp4" #File template for listing
else
  template="$2"
fi

#echo "Template = $2 (${template})"

cntall=`find . -maxdepth 1 -name "202*.mp4" -printf '.' | wc -m`
#cntall=`find . -maxdepth 1 -name "${template}" -printf '.' | wc -m`
let "cntrem = $cntall - $cnt"

#echo "Template = ${template}"
#echo "Count = $cnt"
#echo "Leave = $cntrem"

if [ $cntrem -le "0" ]; then
  exit
fi

videos=`printf "%s\n" 202?-*.mp4 | head -"$cntrem"`
#videos=`printf "%s\n ${template}" | head -"$cntrem"`
echo "$videos"


-- 
Bo Berglund
Developer in Sweden





More information about the ubuntu-users mailing list