In the example you mention, where the expansion for the alias is a single word containing no character that is subject to expansion, it makes no difference how you quote the name _cutf
:
$ alias cutf="_cutf"
$ alias cutf
alias cutf='_cutf'
$ unalias cutf
$ alias cutf='_cutf'
$ alias cutf
alias cutf='_cutf'
$ unalias cutf
$ alias cutf=_cutf
$ alias cutf
alias cutf='_cutf'
As you can see in that interaction, recalling the value of the alias cutf
gave the same result each time. So, yes, the quoting styles are interchangeable here.
It is not relevant that the expansion is to a function name: at least with bash, aliases perform a simple textual substitution (it is not obvious to me in what way defining an alias is useful; directly calling the underlying function seems just as easy).
Here (linebreaks added),
$ task add "first line doesn\'t say much
Second line says a lot but part of this line does not appear in the
resulting description 'truncate -s0 !(temp_file | temp_dir)' truncates
all files to 0 bytes as shown by: '`wc -l *`'"
the whole string is double-quoted, so command substitutions and other expansions will run there. That happens in the shell, before task
sees that string, and you'll need to prevent it with backslashes or putting that part in single quotes.
E.g.
$ printf "%s\n" "...shown by: '\`wc -l *\`'"
...shown by: '`wc -l *`'
So,
task add "...shown by: '\`wc -l *\`'"
would pass the string ...shown by: '`wc -l *`'
to task
. It's up to it what does with that.
If you don't want to use backslashes, here's the way to put it in single quotes:
# aaaaaaaaaaaaaaaaBBBBBBBBBBBaaa
$ printf "%s\n" "...shown by: '"'`wc -l *`'"'"
...shown by: '`wc -l *`'
(The a
's mark the double-quoted parts, the B
's the single-quoted parts. They are just concatenated on the shell command line. The literal single quotes are within the double-quoted strings.)
As for the single quote and the backslash, you don't need to escape a single quote within double quotes, and in fact the backslash will remain there:
$ printf "%s\n" "foo'bar"
foo'bar
$ printf "%s\n" "foo\'bar"
foo\'bar
From what you show, it seems like task
removes at least the first single-quoted string from the argument (plus a word after that, since the removed part was 't say much ... 'truncate
)
The shell will not do that, this works fine:
$ printf "%s\n" "a 'quoted string' to test"
a 'quoted string' to test
What's causing the shell to remove the part of the argument to task
between \
(backslash) and -s
,
It's highly likely it's not the shell doing that.
and how do you prevent the shell from interpreting the above single-quoted command substitution (i.e. '`wc -l *`'
)?
It's not single-quoted, it's double-quoted with quoted single quotes next to it.
Best Answer
Single-quote vs double-quote versions
Let's define the alias using single-quotes:
Now, let's retrieve the definition of the alias:
Observe that no command substitution was yet performed.
Let's do the same, but this time with double-quotes:
Because double-quotes are used, command substitution was performed before the alias was defined.
Single-quote version
Let's try executing the single-quote version:
The single-quote version is equivalent to running:
In both cases, the command substitution is performed when the command is executed.
A variation
Let's consider this alias which uses command substitution and is defined using single-quotes:
Every time that we run this command,
date
is evaluated again. With single-quotes, the command substitution is performed when the alias is executed, not when it is defined.