1
#!/bin/ksh
typeset FILE_SIZE1=$(stat -f '%z' test.txt);
typeset -r BK_STATARGS="-f '%z'"
typeset FILE_SIZE2=$(stat ${BK_STATARGS} test.txt);
echo without arg var ${FILE_SIZE1}
echo with arg var... ${FILE_SIZE2}

Yields....

without arg var 216
with arg var... '216'

Maybe I'm missing the obvious but I can't figure out a fix. I've tried all sorts of things.

1 Answer 1

0

BK_STATARGS is a variable whose content is the 7-character string -f '%z'. First, let's see what happens in the command

stat "${BK_STATARGS}" test.txt

The shell first parses the command into a syntax tree, which here consists of a single simple command, with three tokens: stat, the result of the expansion of ${BK_STATARGS}, and test.txt. Then the shell expands the value of the variable, in order to determine the second word, which is -f '%z' (that same 7-character string). Finally the shell executes the command in the first word, passing the subsequent words as command line arguments, so stat is executed with two arguments -f '%z' and test.txt.

Let's now turn to the more complex command

stat ${BK_STATARGS} test.txt

The processing is the same until the expansion of the value of the variable. Since the variable substitution is not in double quotes, its value is treated as a whitespace-separated list of words. There is one whitespace character in the string, so it is split into two words, and stat receives three arguments: -f, '%z' and test.txt.

The single quotes are part of shell syntax: they are recognized at the parsing stage. They have no special meaning when they're in a string, even if the string gets split after variable expansion.

Since % and z are not special characters, you don't need to quote them:

typeset -r BK_STATARGS="-f %z"
typeset FILE_SIZE2=$(stat ${BK_STATARGS} test.txt)

In general, to pass multiple arguments to a command, you need to use an array instead of a string.

typeset -a BK_STATARGS; BK_STATARGS=(-f '%z')
typeset FILE_SIZE2=$(stat "${BK_STATARGS[@]}" test.txt)

"${BK_STATARGS[@]}" is the syntax to expand an array into its list of elements. Even though it looks like a single word due to the double quotes, it's actually split into multiple words due to the [@] subscript, working like "$@.

You must log in to answer this question.

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