0

I'm in the process of writing a shell script which sets up my osx machine exactly how I like each time I get a new machine. One piece of command line sugar I really like is the 'up arrow bash history search'. As the ask ubuntu post says, adding the line:

bind '"\e[A":history-search-backward'

to my ~/.bashrc will do this for me, but, I'd like this automated from my script...

To achieve it I've had the most success with printf, but I need to escape the quotes and escape sequence immediately after bind ('"\e), something like:

printf "bind \'\"\\e[A\":history-search-backward\'" >> ~/.bashrc

but in that example the escape sequence doesn't escape so in my ~/.bashrc i get the line:

bind '"^[[A":history-search-backward'

I've tried numerous different combinations of quoting/escaping/interpolation and had little success, does anyone have some character escaping foo that could achieve this or even just an explaination on why this won't work, google is particularly thin on the ground for this especially around the \e escaping.

Joe
  • 678
  • 9
  • 24
  • 3
    Save yourself the trouble and use a [here document](https://stackoverflow.com/questions/25214084/cant-get-ascii-art-to-echo-to-console) when you want to write an arbitrary string – that other guy Oct 24 '18 at 23:05

2 Answers2

2

Use a here-document:

cat <<'EOF' >>~/.bashrc
bind '"\e[A":history-search-backward'
EOF

The quotes around EOF mean that the contents of the here-document will be treated like a single-quoted string, so $ will be treated literally rather than as a variable prefix. That doesn't matter in this particular string, but could in more general applications.

Barmar
  • 741,623
  • 53
  • 500
  • 612
1

A quoted here-document is the simplest way to do this (as in that other guy's comment and Barmar's answer), but if you really want to use printf, there are a couple of ways to do that. Before I get to the major problem, there are two subsidiary ones: you don't need to escape the single-quotes in the string, and you do need to add a newline (\n) at the end (unlike echo, printf doesn't add this automatically).

The big problem with your current command is that you're putting the string you want in printf's first argument, which it treats as a format string -- among other things, that means that it interprets escape sequences in it. After the shell has already interpreted them. Because there are two phases of escape interpretation, you need to quadruple the escape you want to end up in the final string:

printf "bind '\"\\\\e[A\":history-search-backward'\n"

Alternately, you can put the string in the second argument to printf, and use a format string that just includes it literally (the %s directive) without the extra level of escape interpretation:

printf '%s\n' "bind '\"\\e[A\":history-search-backward'"

Note that the \n has to be in the format string, so it gets translated to an actual newline.

Or you could just use a quoted here-document.

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151
  • I've marked this as the correct answer as it answers the specific question I asked, however, I've implemented Barmar & that other guy solution of using a quoted here-document as it's probably clearer and cleaner. – Joe Oct 25 '18 at 08:19