bash quote escaping change in 4.4

bash -c "/tmp/printargs \\"abc\\""

Does not escape what you think it does. A backslash-backslash is an escaped backslash, handled by the calling shell — so that is the same as running:

/tmp/printargs \abc\

because the double-quotes are not escaped. You could have just written:

bash -c '/tmp/printargs \abc\'

I'm guessing you actually wanted:

bash -c "/tmp/printargs \"abc\""

which escapes the double quotes, passing a quoted "abc" to the bash -c.

(I'm guessing the different behavior you're seeing is different versions of bash handling the escaped nothing at end of input differently.)

Perl version of printargs (slightly improved behavior):

#!/usr/bin/perl
use feature qw(say);

for (my $i = 0; $i < @ARGV; ++$i) {
        say "$i: |$ARGV[$i]|";
}

bash -c "/tmp/printargs \\"abc\\""

Are you sure this is what you want to do? If you run that with set -x in effect, you'll see that the command that runs, is

bash -c '/tmp/printargs \abc\'

i.e. you're passing the shell a string that ends in a backslash. Your first quoted string contains an escaped backslash, then you have an unquoted abc, an escaped backslash, and then an empty quoted string. (Note how the syntax highlighting done by Stackexchange shows the abc is not quoted.)

The unquoted backslash at the end of input doesn't make much sense. A backslash either escapes the following character, or starts a continuation line, where it's deleted along with the following newline, like here:

$ bash -c $'echo "foo\\\nbar"'                                                                                                              
foobar 

This case has neither. You're possibly trying to do either of these:

bash -c "/tmp/printargs \"abc\""
bash -c '/tmp/printargs "abc"'

Both of which produce the output ARG |abc|.


We can see the difference between shells with a bit simpler test:

$ bash -c 'echo $BASH_VERSION; echo abc\'
4.4.12(1)-release
abc\

$ ./bash -c 'echo $BASH_VERSION; echo abc\'
4.3.30(1)-release
abc

$ dpkg -l dash |grep ^i
ii  dash           0.5.8-2.4    amd64        POSIX-compliant shell
$ dash -c 'echo abc\'
abc\

$ dpkg -l zsh |grep ^i
ii  zsh            5.3.1-4+b2   amd64        shell with lots of features
$ zsh -c 'echo abc\'
abc

If I had to guess, I'd start looking for the source of the change in this change:

This document details the changes between this version, bash-4.4-alpha, and
the previous version, bash-4.3-release.

1.  Changes to Bash

cccc. Fixed a bug that resulted in short-circuited evaluation when reading
      commands from a string ending in an unquoted backslash, or when sourcing
      a file that ends with an unquoted backslash.