21

Trying to create a small script capable to write a part off the script in the output file without any changes, (as is)

source file text

echo "
yellow=`tput setaf 3`
bel=`tput bel`
red=`tput setaf 1`
green=`tput setaf 2`
reset=`tput sgr0
echo"#${green}Installing packages${reset}#" &&
" >> output.txt

Desired output:

yellow=`tput setaf 3`
bel=`tput bel`
red=`tput setaf 1`
green=`tput setaf 2`
reset=`tput sgr0
echo"#${green}Installing packages${reset}#" &&

What I'm getting is:

yellow=^[[33m
bel=^G
red=^[[31m
green=^[[32m
reset=^[(B^[[m
echo"#${green}Installing packages${reset}#" &&

Using CentOS 7 Minimal fresh install Looking for a solution to be applied to the full script/text, no the line per line changes, I suppose may be done using sed too ...

Zaza
  • 458
  • 2
  • 7
  • 15

4 Answers4

37

You need to escape the backticks (`):

#!/bin/bash
echo "
yellow=\`tput setaf 3\`
bel=\`tput bel\`
red=\`tput setaf 1\`
green=\`tput setaf 2\`
reset=\`tput sgr0\`
" >> output.txt

As a bonus:

I prefer using this method for multiline:

#!/bin/bash
cat << 'EOF' >> output.txt
yellow=$(tput setaf 3)
bel=$(tput bel)
red=$(tput setaf 1)
green=$(tput setaf 2)
reset=$(tput sgr0)
EOF
chepner
  • 497,756
  • 71
  • 530
  • 681
Nick
  • 597
  • 4
  • 15
  • Thanks, covering quotes with forward slash work, but I have 550 line script cumming next and I presume echo will do some minor (difficult to chase changes) , Would there be any solution applying to the full script, to be sure no changes are done when written in to the output file ? – Zaza Nov 12 '16 at 12:43
  • I'm not sure why you would move scripts around like this? You could have the script stored and just `cp` it around. – Nick Nov 12 '16 at 12:55
  • I'm creating a nagios install/config script, on some stage script must create an output file , upload it to the slave/remote server and run it there. – Zaza Nov 12 '16 at 13:06
  • I've updated the here-document to avoid constant quoting by quoting the delimiter itself, which makes the here-document behave as if it were a single-quoted string. Also, prefer `$(...)` to backticks. In some sense, the `cat` solution is less efficient, since it runs an external process while `echo` is built-in, but in this case it's a small price to pay for readability. – chepner Nov 12 '16 at 15:46
  • The Firs solution with forward slashes is not really working for me, because color definitions are stopping working that way.. But with Bracket all solutions are working just fine, echo and cat, both and color definition do not require modifications. Going to update the header with the solution I found useful . Thank you – Zaza Nov 12 '16 at 22:12
8

Use single quote to prevent expansions:

echo '
yellow=`tput setaf 3`
bel=`tput bel`
red=`tput setaf 1`
green=`tput setaf 2`
reset=`tput sgr0`
' >> output.txt

For more details see Difference between double and single quote.


If your text includes single quote then the above may not work. In that case using a here doc would be safer. For example, the above will break if you insert a line: var='something'.

Using a here doc it will be like this:

cat >> output.txt <<'EOF'
yellow=`tput setaf 3`
bel=`tput bel`
red=`tput setaf 1`
green=`tput setaf 2`
reset=`tput sgr0`
var='something'
EOF
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Jahid
  • 21,542
  • 10
  • 90
  • 108
  • I know the difference but in this case whenn I'm using the single quote, then bash executes the source file, which means echo ' is getting ignored fully – Zaza Nov 12 '16 at 12:30
  • @eadmineadmin : Please explain the procedure which gives you unexpected behavior... – Jahid Nov 12 '16 at 12:46
  • it simple executes the file ignoring the echo ' , when echo " works fine but makes undesired changes when copying as shown higher – Zaza Nov 12 '16 at 12:51
  • @eadmineadmin : I think heredoc will be safer in this case. see my edit. – Jahid Nov 12 '16 at 15:51
2

Just a late addition:

The echo 'string' >> output command is simple and great. But it may will give you the '...: Permission denied' error combined with sudo.

I recently had a lil issue with sudo echo 'string \n other string \n' > /path/to/file

What worked for me the best:
printf "Line1\nLine2\nLine3" | sudo tee --append /path/to/file

It's an extra that you actually have the string printed to the stdout too, so you will see what was written to the file.

Gergely M
  • 583
  • 4
  • 11
0

Thanks to chepner

Best solution I found is :

echo '
yellow=$(tput setaf 3)
bel=$(tput bel)
red=$(tput setaf 1)
green=$(tput setaf 2)
reset=$(tput sgr0)
echo"#${green}Installing packages${reset}#"
' >> output

With this solution all text goes to output file without modifications and color definitions are working without modifications too.

Zaza
  • 458
  • 2
  • 7
  • 15