Different languages and contexts have different escape characters and sequences. The '\' has special meaning in C, PHP, the shell and a good many other languages, although the rules are not always the same (as we will see below!). The question in this thread is specifically about the shell, and about
printf in shell context which adds its own rules for '\'.
I usually think that people who seek out edge cases and obscure command superpositions really have too much time on their hands!
There are also differences in printf usage among shells, so we will restrict what follows to Bash which uses a built-in printf.
The obscurity of the case posted here is caused by the fact that the backslashes are handled twice, with different rules!
First, because the format string is not quoted, the shell applies its rules for special meaning of the backslash:
Then printf receives the resulting format string, and applies its own rules:
As pan64 has shown, both the case of
\\\\n and
\\\\\n are reduce by the shell to
\\n, which printf interprets as
\ followed by the letter
n, or literal
\n.
As noted above, quoting is important, and I can hardly think of a useful case where you would
not want to quote a printf format string! But there are still two choices... single quotes and double quotes. In this case the single quoted string is usually the winner, it protects the format string from shell interpretation and tells printf what you really mean!
Now, all that said, it is interesting to compare the different patterns that result from unquoted, single quoted and double quoted format strings. Following are examples of one through eight backslashes followed by 'n', in each case, using the OP's printf specifiers.
Unquoted format string - slashes escaped by shell,
\\=\,
\n=n:
Code:
xxx=string, (nl)=newline Printf sees: Result:
printf %-5s\n "01" # %-5sn xxx n
printf %-5s\\n "02" # %-5s\n xxx (nl)
printf %-5s\\\n "03" # %-5s\n xxx (nl)
printf %-5s\\\\n "04" # %-5s\\n xxx n
printf %-5s\\\\\n "05" # %-5s\\n xxx n
printf %-5s\\\\\\n "06" # %-5s\\\n xxx \(nl)
printf %-5s\\\\\\\n "07" # %-5s\\\n xxx \(nl)
printf %-5s\\\\\\\\n "08" # %-5s\\\\n xxx \\n
Single quoted format string - no shell escape handling
Code:
xxx=string, (nl)=newline Printf sees: Result:
printf '%-5s\n' "01" # %-5s\n xxx (nl)
printf '%-5s\\n' "02" # %-5s\\n xxx \n
printf '%-5s\\\n' "03" # %-5s\\\n xxx \(nl)
printf '%-5s\\\\n' "04" # %-5s\\\\n xxx \\n
printf '%-5s\\\\\n' "05" # %-5s\\\\\n xxx \\(nl)
printf '%-5s\\\\\\n' "06" # %-5s\\\\\\n xxx \\\n
printf '%-5s\\\\\\\n' "07" # %-5s\\\\\\\n xxx \\\(nl)
printf '%-5s\\\\\\\\n' "08" # %-5s\\\\\\\\n xxx \\\\n
Double quoted format string - slashes escaped by quoting, \\=\, \n=\ followed by n
Code:
xxx=string, (nl)=newline Printf sees: Result:
printf "%-5s\n" "01" # %-5s\n xxx (nl)
printf "%-5s\\n" "02" # %-5s\n xxx (nl)
printf "%-5s\\\n" "03" # %-5s\\n xxx \n
printf "%-5s\\\\n" "04" # %-5s\\n xxx \n
printf "%-5s\\\\\n" "05" # %-5s\\\n xxx \(nl)
printf "%-5s\\\\\\n" "06" # %-5s\\\n xxx \(nl)
printf "%-5s\\\\\\\n" "07" # %-5s\\\\n xxx \\n
printf "%-5s\\\\\\\\n" "08" # %-5s\\\\n xxx \\n
Note the different alternations in output that result from the different meaning of backslashes in each case, interacting with the printf rules. There are additional cases that can arise too, but I leave that as an exercise for the truly bored!
The lesson to be learned: Always single quote
printf format strings in shell scripts, and use the time you save for better purposes!