Search code examples
linuxbashfindzip

How to prepare quoted parameters in bash?


The below bash code snippet explains my problem. I want to generate the arguments after the -i, at the time of calling the zip command.

#!/bin/bash
from_date=2020-05-17
to_date=2020-06-17 #tomorrow's date

w='"*a*" "*b*"'
# doesn't work
find . -newermt "$from_date" ! -newermt "$to_date" | zip zipf.zip -@ -i $w

#works
find . -newermt "$from_date" ! -newermt "$to_date" | zip zipf.zip -@ -i "*a*" "*b*"

The last line works because I hardcoded the parameters. However, if I use the w variable, and I have tried many ways of writing it but without success, it comes up with an error like: zip error: Nothing to do! (zipf.zip) What value of the w variable will work in this case?


Solution

  • ... | zip zipf.zip -@ -i "*a*" "*b*"
    

    This is two separate quoted arguments - the shell thus doesn't expand either pattern and they are taken by zip as arguments to -i.

    w='"*a*" "*b*"'
    ... | zip zipf.zip -@ -i $w
    

    Since you didn't quote $w, when it's expanded, it's subject to word splitting (What you want) and pathname expansion (Which you don't want bash to do). You don't have any files that match the patterns in it (Probably because of the double quotes, which are part of the words).

    What you can do instead is use an array to hold the patterns:

    w=("*a*" "*b*")
    ... | zip zipf.zip -@ -i "${w[@]}"
    

    (The quotes here are important; they cause the array to be expanded into quoted strings so pathname expansion isn't done)