0

I created a bash shell script to zip all files that match a pattern as follows:

#!/bin/bash
zip $1 $2

When I run the above script using ./myScript.sh myzip test*, only one file that starts with the name test is added to the zip even though my directory has 2 files (test1 and test2) that match the pattern.

If I run the zip command directly from the shell, it works as expected and adds both test1 and test2 to myzip. But when I use a script to do this, it adds only 1 file.

What am I missing?

0

1 Answer 1

4

When you call your script like

./myScript.sh myzip test*

you give the script the arguments myzip, test1 and test2. The last two arguments are expanded from the test* pattern by the shell before the script is actually invoked. Note that test2 will be available in $3, but your script never uses $3.

You can solve this in two ways:

  1. Pick off the archive name from the argument list, then shift the list to remove the archive name from the list of positional parameters, and finally use "$@" (the remaining arguments) in the call to zip:

    #!/bin/sh
    
    archive=$1
    shift
    
    zip "$archive" "$@"
    

    Since all variables are quoted, this additionally means that you'd be able to work with filenames that contain whitespace etc.

    With bash, this could possibly be written a bit more unreadably as

    #!/bin/bash
    
    zip "$1" "${@:2}"
    
  2. The zip utility knows how to expand shell globbing patterns itself. Use this fact to give the script a pattern rather than a list of filenames:

    #!/bin/sh
    
    zip "$1" "$2"
    

    This script should be called as

    ./myScript.sh myzip 'test*'
    

    The quoting of test* stops the shell from expanding the pattern (which is what we rely on in the first alternative).

2
  • Always quote variable(unless there is a good reason not to: you want that behaviour), if they need them or not: so archive="$1" not archive=$1. There is no point carrying around in our heads a list of edge cases. Dec 1, 2019 at 11:04
  • Note the 1st example is able to be called in both ways (test* and 'test*') . It is therefore more robust. Dec 1, 2019 at 11:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .