ThisIsMe
ThisIsMe

Reputation: 3

Why doesn't zsh syntax work in this script?

I'm just trying to understand what is happening here, so that I understand how to parse strings in shell scripts better.

I know that usually, when you try to pass a string of arguments separated by spaces directly to a command, they will be treated as a single string argument and therefore not recognized:

>check="FileA.txt FileB.txt"
>ls $check
ls: cannot access FileA.txt FileB.txt: No such file or directory

However, in this script two arguments are taken each as space separated strings. In this case, both strings are recognizes as lists of arguments that can be passed to different commands:

testscript.sh

while getopts o:p: arguments
do  
    case $arguments in
    o) olist="$OPTARG";;
    p) plist=$OPTARG;;
    esac
done
echo "olist"
ls -l $olist
echo "plist"
ls -l $plist

the output is then as follows:

>testscript.sh -o "fileA.txt fileB.txt" -p "file1.txt file2.txt"
Olist
fileA.txt
fileB.txt
plist
file1.txt
file2.txt

What is different here? Why are the space separated strings suddenly recognized as lists?

Upvotes: 0

Views: 546

Answers (2)

Adaephon
Adaephon

Reputation: 18329

Your script does not start with a #!-line and does therefore not specify an interpreter. In that case the default is used, which is /bin/sh and not your login shell or the shell you are starting the script from (unless that is /bin/sh of course). Chances are good that /bin/sh is not a zsh, as most distributions and Unices seem to use sh, bash, dash or ksh as default shell. All of which handle parameter expansion such that strings are handles as lists if the parameter was not quoted with double-quotes.

If you want to use zsh as interpreter for your scripts, you have to specify it in the first line of the script:

#!/usr/bin/zsh

Modify the path to wherever your zsh resides.

You can also use env as a wrapper:

#!/usr/bin/env zsh

This makes you more independent of the actual location of zsh, it just has to be in $PATH.

Upvotes: 2

Sylvain Leroux
Sylvain Leroux

Reputation: 51980

As a matter of fact (using bash)...

sh$ check="FileA.txt FileB.txt"
sh$ ls $check
ls: cannot access FileA.txt: No such file or directory
ls: cannot access FileB.txt: No such file or directory

When you write $check without quotes, the variable is substituted by its content. Insides paces (or to be precises inside occurrences of IFS) are considered as field separators. Just as you where expecting it first.

The only way I know to reproduce your behavior is to set IFS to something else than its default value:

sh$ export IFS="-"
sh$ check="FileA.txt FileB.txt"
sh$ ls $check
ls: cannot access FileA.txt FileB.txt: No such file or directory

Upvotes: 1

Related Questions