bug#20553: 'echo -e' does not escape backslash correctly
Hi, On Mon, May 11, 2015 at 11:17:34PM +0100, Stephane Chazelas wrote: 2015-05-11 23:50:25 +0200, Jo Drexl (FFGR-IT): Hi guys, I had to write a Windows bat file for twentysomething users and - as Linux geek - wrote a small Bash script for it. The code in question is as follows: echo -e net use z: srv\\aqs /persistent:no /user:%USERNAME% $BG_PASSWD\r [...] If that's a bash script, then that has nothing to do with GNU coreutils as bash has its own builtin version of echo. In any case, there's no bug here. and GNU coreutils echo or the bash one behave the same. \ is used as an escape character both for the bash language within double quotes, and for echo -e. echo -e Passes 3 arguments to echo: echo, -e and \\ So you need to add another handful of \ characters: $ echo -e \\ $ /bin/echo -e \\ Erik
bug#20553: 'echo -e' does not escape backslash correctly
2015-05-11 17:36:50 -0600, Eric Blake: On 05/11/2015 04:14 PM, Pádraig Brady wrote: echo -e net use z: srv\\aqs /persistent:no /user:%USERNAME% $BG_PASSWD\r 'echo -e' is non-portable. POSIX recommends that you use printf instead, as the POSIX version of echo is supposed to behave as follows: $ echo -e 'a\nb' -e a\nb [...] Strictly speaking without XSI (Unix conformance), the behaviour of that command is unspecified because the arguments contain backslash. With XSI, the behaviour is specified but the expected output is: -e anewlinebnewline You are relying on non-POSIX behavior for backslash interpolation. Note echo is not portable to other systems, and if that's required, In fact, it's not even portable to bash: $ shopt -s xpg_echo tells bash to turn on POSIX rules for echo, invalidating any bash script that relies on 'echo -e'. xpg_echo alone doesn't make bash's echo POSIX compliant. It just means -e is implicit. It wouln't break scripts that use echo -e, just script that use echo without -e and expect escape sequences not to be expanded. To have a Unix (POSIX+XSI) conformant echo, you need both the posix (set -o posix) and xpg_echo (shopt -s xpg_echo) options. Those can also be enabled via the environment (BASHOPTS, SHELLOPTS, POSIXLY_CORRECT) or at compile time. bash will also enable posix when called as sh. See https://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo for more info. printf(1) is a better option, though that will have different quoting again due to the % chars etc. % doesn't need quoting in shell. But yes, printf is more portable. % needs escaped (with %) in the format argument though, which is probaby what Pádraig was refering to. -- Stephane
bug#20553: 'echo -e' does not escape backslash correctly
tag 20553 notabug close 20553 stop On 11/05/15 22:50, Jo Drexl (FFGR-IT) wrote: Hi guys, I had to write a Windows bat file for twentysomething users and - as Linux geek - wrote a small Bash script for it. The code in question is as follows: echo -e net use z: srv\\aqs /persistent:no /user:%USERNAME% $BG_PASSWD\r I expected the created files being as such: net use z: \\srv\aqs /persistent:no /user:%USERNAME% user-password but got: net use z: \srvqs /persistent:no /user:%USERNAME% user-password Without the parameter e the code for a working file had to be: echo net use z: \\srv\aqs /persistent:no /user:%USERNAME% $BG_PASSWD but missed the Windows-newline carriage return (\r) - adding that without changing the echo command didn't print out the carriage return character but the literal backslash-R, as the default behaviour (parameter E) indicates. Long story short: Escaping doesn't work correctly, either it's the Bash interfering (but only escaping the double backslashes, and afterwards echo -e escaping everything correctly), or the double backslash escape doesn't work at all. It CAN be healed by using single quotes, but then variable expansion doesn't work, or by using a variable workaround: BG_SHARE='srv\\aqs' echo -e net use z: $BG_SHARE /persistent:no /user:%USERNAME% $BG_PASSWD\r but I'm pretty positive this is a workaround, not the way it should work. Maybe you dig into it, if you have the time. Since I found nothing worthy googleing the issue, it seems like a quite uncommon situation I'm in. BR Jo P.S.: It's a standard Debian Wheezy without clickery GUI. No funny changes to the default behaviour of Bash or the login shell. The shell _and_ echo -e are processing the \'s To get the shell to stop you can use single quotes like: echo -e 'net use z: srv\\aqs /persistent:no /user:%USERNAME% $BG_PASSWD\r' Or to leave to shell to also process \r you can: echo $'net use z: srv\\aqs /persistent:no /user:%USERNAME% $BG_PASSWD\r' Note echo is not portable to other systems, and if that's required, printf(1) is a better option, though that will have different quoting again due to the % chars etc. cheers, Pádraig.
bug#20553: 'echo -e' does not escape backslash correctly
Hi guys, I had to write a Windows bat file for twentysomething users and - as Linux geek - wrote a small Bash script for it. The code in question is as follows: echo -e net use z: srv\\aqs /persistent:no /user:%USERNAME% $BG_PASSWD\r I expected the created files being as such: net use z: \\srv\aqs /persistent:no /user:%USERNAME% user-password but got: net use z: \srvqs /persistent:no /user:%USERNAME% user-password Without the parameter e the code for a working file had to be: echo net use z: \\srv\aqs /persistent:no /user:%USERNAME% $BG_PASSWD but missed the Windows-newline carriage return (\r) - adding that without changing the echo command didn't print out the carriage return character but the literal backslash-R, as the default behaviour (parameter E) indicates. Long story short: Escaping doesn't work correctly, either it's the Bash interfering (but only escaping the double backslashes, and afterwards echo -e escaping everything correctly), or the double backslash escape doesn't work at all. It CAN be healed by using single quotes, but then variable expansion doesn't work, or by using a variable workaround: BG_SHARE='srv\\aqs' echo -e net use z: $BG_SHARE /persistent:no /user:%USERNAME% $BG_PASSWD \r but I'm pretty positive this is a workaround, not the way it should work. Maybe you dig into it, if you have the time. Since I found nothing worthy googleing the issue, it seems like a quite uncommon situation I'm in. BR Jo P.S.: It's a standard Debian Wheezy without clickery GUI. No funny changes to the default behaviour of Bash or the login shell. signature.asc Description: This is a digitally signed message part
bug#20553: 'echo -e' does not escape backslash correctly
On 05/11/2015 04:14 PM, Pádraig Brady wrote: echo -e net use z: srv\\aqs /persistent:no /user:%USERNAME% $BG_PASSWD\r 'echo -e' is non-portable. POSIX recommends that you use printf instead, as the POSIX version of echo is supposed to behave as follows: $ echo -e 'a\nb' -e a\nb You are relying on non-POSIX behavior for backslash interpolation. Note echo is not portable to other systems, and if that's required, In fact, it's not even portable to bash: $ shopt -s xpg_echo tells bash to turn on POSIX rules for echo, invalidating any bash script that relies on 'echo -e'. printf(1) is a better option, though that will have different quoting again due to the % chars etc. % doesn't need quoting in shell. But yes, printf is more portable. -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature
bug#20553: 'echo -e' does not escape backslash correctly
2015-05-11 23:50:25 +0200, Jo Drexl (FFGR-IT): Hi guys, I had to write a Windows bat file for twentysomething users and - as Linux geek - wrote a small Bash script for it. The code in question is as follows: echo -e net use z: srv\\aqs /persistent:no /user:%USERNAME% $BG_PASSWD\r [...] If that's a bash script, then that has nothing to do with GNU coreutils as bash has its own builtin version of echo. In any case, there's no bug here. and GNU coreutils echo or the bash one behave the same. \ is used as an escape character both for the bash language within double quotes, and for echo -e. echo -e Passes 3 arguments to echo: echo, -e and \\ Same as echo -e '\\' And echo then treats \\ as an escaped \. You've got another problem in that escape sequences are expanded in your variables. Here, you want: printf '%s\r\n' net use z: srv\\aqs /persistent:no /user:%USERNAME% $BG_PASSWD or: printf '%s\r\n' 'net use z: \\srv\aqs /persistent:no /user:%USERNAME% '$BG_PASSWD or: printf 'net use z: srv\\aqs /persistent:no /user:%%USERNAME%% %s\r\n' $BG_PASSWD etc... -- Stephane