In
echo Variable "$var" is not initialised.
You're passing 5 arguments to echo
(6 if you count echo
, the argv[0]
), echo
will output them separated by a space character terminated with a newline.
In:
echo "Variable $var is not initialised."
You're passing 1 argument (2 if you count echo
).
In this particular case and in most cases, that is going to be functionally equivalent.
The second means less work for the shell to parse the command and store it into arguments before running echo
and less work for echo
to go through its arguments.
That's unlikely to make a very significant difference in terms of performance. In my tests, I see it making a small difference with some echo
/shell
combinations like bash
with its builtin, but hardly any in others.
Other reasons why you may want to pass one argument instead of several:
If you want more than a space between the arguments: echo a b
would output a b
, you need echo 'a b'
to output a b
.
In things like echo "$opt" is an invalid option
, with some echo
implementations like the echo
builtin of bash
, that wouldn't work with opt=-e
(or -E
or -neE
...) while echo "$opt is an invalid option"
would be OK.
In echo foo bar
, you're passing 2 arguments (beside the echo
one) 3 byte long each, that is 2 pointers (8 byte each on 64bit systems) and 8 bytes including the \0
string delimiters for the actual strings, so 24 bytes in total on 64bit systems.
While it's one pointer and 8 bytes for echo 'foo bar'
(16 bytes total). When calling the external echo
executable with a large list of arguments, that can make you reach the limit on the size of the arguments sooner (though note that Linux also has a limit (128KiB) on the maximum size of a single argument).
In any case here, for arbitrary data (like that $var
whose content we don't know (though from the context here we could derive that it contains only alnums and underscore)), you want to use printf
, not echo
:
printf >&2 '%s\n' "Variable $var is not initialised."
Or:
printf >&2 'Variable %s is not initialised.' "$var"
(here sent to stderr as that looks like it's meant to be an error to the user and not part of the normal output produced by your script).
And in that case, beside the format, it has to be one single argument passed to printf
.
Another advantage of that approach is that it makes it possible to translate the messages in the user's language where you can provide ready made translations of that Variable %s is not initialised.
format in all supported languages (and using gettext
or ksh93/bash's $"..."
to retrieve them).
echo
gets 5 args and in the second 1 arg. Butecho
concats its args on spaces - a single space per - and so it prints the same. Both uses are perfectly safe. You would see the difference if you didecho "Variable $var is not initialised."
though. – mikeserv Jan 09 '15 at 16:00echo
implementations (includingbash
's under some circumstances), it's not safe in that escape sequences in$var
will be expanded. Generally, you wantprintf
to print arbitrary data. – Stéphane Chazelas Jan 09 '15 at 16:11$var
's expansion as an argument. But I wasn't even considering the possibility of backslash escapes in the expansion. Then again, if there are such, they will at least be preserved forecho
to interpret. But yes, for a literal representation of string the most reliable method of getting such is as an explicitly declared%s
tring argument toprintf
. – mikeserv Jan 09 '15 at 16:33