1

How can I stop the eval statement from evaluating when it's being appended to a file as part of a cat << __EOF__ command?

TL;DR

I manage services on a large number of Linux servers. Frequently, I end up with a headache, due to some of the default terminal colors specified by LS_COLORS, so I wrote a quick script that I could just paste into the terminal to fix the color issues. This script is:

cat >> ~/.dircolors << __EOF__
OTHER_WRITABLE 01;30;41 # dir that is other-writable (o+w) and not sticky
__EOF__
cat >> ~/.bashrc << __EOF__

# Customize directory listing colors.
eval `dircolors ~/.dircolors`
export LS_COLORS
__EOF__
eval `dircolors ~/.dircolors`

This works fine for the session where I specify it, but when I log back in, I get the following error:

-bash: 30: command not found
-bash: 41:: command not found
[me@myserver ~]$

As I'm sure some of you have realized, when I look at my .bashrc, the last 4 lines look like this:

# Customize directory listing colors.
eval LS_COLORS='ow=01;30;41:';
export LS_COLORS
export LS_COLORS

However, if I change it back to:

eval `dircolors ~/.dircolors`

everything works fine on the next login.

2

What's evaluating here isn't eval. The word eval in your script is completely inert. You'll note that it appears in the output, after all.

What is evaluating is the command substitution (the part in backticks). To include the literal backticks in the text that is written to the file, protect them with backslashes:

cat >> ~/.bashrc << __EOF__

# Customize directory listing colors.
eval \`dircolors ~/.dircolors\`
export LS_COLORS
__EOF__

Alternatively, make the here-document a literal one, i.e. one that takes the text as is rather than performing variable and command substitution. You do that by quoting any part of the end marker after the << operator.

cat >> ~/.bashrc <<\__EOF__

# Customize directory listing colors.
eval `dircolors ~/.dircolors`
export LS_COLORS
__EOF__
1
  • Ended up going with the second option. Worked like a charm. I should've realized what was actually happening. For as long as I've been around Linux/Unix, it's amazing just how many gaps I keep finding in my knowledge. Thanks.
    – Deacon
    Jun 2 '16 at 12:22
1

The ; divides statements in shell code, so what is happening is the eval runs LS_COLORS=ow=01 and then the command 30 and then the command 41:. This can be observed with some test echo calls:

% echo 'test;echo hi;echo there'
test;echo hi;echo there
% eval echo 'test;echo hi;echo there'
test
hi
there
% 

One solution involves more quoting:

% eval "echo 'test;echo hi;echo there'"
test;echo hi;echo there
% 

Such that eval only sees an echo command (with some args) and not a list of ; delimited commands.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.