1

I wrote a simple script.

read -p "Enter the path: " path echo "$path" 

I give the input as

$HOME 

And the output is:

$HOME 

And if I write

echo "$HOME" 

outputs

/home/sam 

so why not in the former case?

9
  • 4
    Basically for the same reason why the C code char *str = "foo()"; printf("%s\n", str); doesn't call the function foo(). What is read with read, and what you print with echo is just data, not shell code. The shell isn't a macro processor that goes back to look at the expanded text to parse it again for further expansions. And it's very well that it isn't, since otherwise people could cause all kinds of havoc with e.g. filenames containing stuff that looks like shell syntax or expansions. Commented Jan 8, 2022 at 14:13
  • @ilkkachu then why does echo "$HOME" gives an output /home/sam. Commented Jan 8, 2022 at 14:17
  • 2
    Because now the command line, the command that actually gets parsed and interpreted for shell syntax does contain the expansion $HOME. Same as how echo "$path" expands $path. Similar to how printf("%s\n", foo()); does call the function. It's the difference between code and data. Commented Jan 8, 2022 at 14:20
  • The shell evaluates variables in double quotes but not in single quotes. The read function is neither. It simply sets input into a variable. Just as a mental exercise, imagine how dangerous it would be if read always evaluated the variables. Commented Jan 8, 2022 at 14:25
  • 1
    For the "how" rather than the "why" see How to expand variables inside read? Commented Jan 8, 2022 at 15:29

1 Answer 1

1

path becomes the string $PATH, not the "interpretation" of it. That interpretation only happens in specific contexts – for example, if you type it "bare" on an interactive shell command prompt; but definitely not in read (otherwise you couldn't use read to read text files containing $, for example!).

Remember, expansion is a functionality that you never want to have enabled everywhere – it would make it hard to write programs that pass around variables as variables, instead of their content. Thus, programming language designers (or in the case of shells, decades of more or less organic development) decide where that expansion happens, and where not. There's not really a "why" here: it's how it's defined.

You can eval value="$path" if you wish, then you get that. I do not recommend that, as it basically makes your entry a shell prompt and if the user enters, for example, $(rm -rf /), that would allow them to delete everything...

All in all, I think this is more of a software design problem: what kind of things do you want to allow the user to do?

In this case, $HOME might pretty much be the only "special" case you'd want to allow. I'd recommend replacing that with ~, as it's the canonical short form, and do something like:

read "Enter foo bar baz:" raw_path if [[ ( ! -d "${raw_path}" ) && "${raw_path:0:1}" = "~" ]]; then _path="${HOME}${raw_path:1:}" else _path="${raw_path}" fi 
0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.