0

Below I have an example which confuses me a bit, any help would be appreciated.

I bind a normal command line command (ls) to a new variable. If I echo it it the output is just the command (ls) but if I just use the variable without echo i get the result of the command but why?? Is it because $listdir gets translated to ls so I just get the output? And if I use the echo command it will be interpreted as a string?

router@test:~/scripting$ listdir=ls
router@test:~/scripting$ echo "$listdir"
ls

----- VS ----
router@test:~/scripting$ $listdir
basicLoop.sh         fileflood.sh .......

Thank you for any help!

3
  • 1
    What is the behavior that you expect? Commented Mar 14, 2021 at 1:48
  • The $listdir gets expanded, and the first word (ls here, which is also the only word for this case) of the expansion is interpreted as a command, and subsequent words, if any, as arguments. Commented Mar 14, 2021 at 1:56
  • Uh I think the only answer here is Yes. Not enough to post! Commented Mar 14, 2021 at 8:02

2 Answers 2

1

By doing listdir=ls you literally assign a string "ls" to the $listdir variable. So if you run echo $listdir now it will just expand into echo ls, which (as you may have guessed) will just print "ls" onto a screen. If you want to store a result of a command into a variable you can wrap the command in `` or $() (eg. listdir=$(ls) or listdir=`ls`).

jarmusz@emacs~$ listdir=`ls`
jarmusz@emacs~$ echo "$listdir"
dls
docs
music
...

If you want to store just a name of the command and run it later you can do it like this:

jarmusz@emacs~$ listdir=ls
<some other commands...>
jarmusz@emacs~$ echo `$listdir`
dls docs music ...

In this example, echo `$listdir` will expand into echo `ls` and then into echo dls docs music...

Sign up to request clarification or add additional context in comments.

Comments

1

When bash is interpreting the commands you feed to it, the first thing it will do is expand any expansions it is given. So when you give it $listdir by the time bash starts to execute the value it is given, all it knows is that it was given the value ls. It does not care where the value came from, only what the value is.

Lets look at the trace given after running set -x, which instructs bash to prints to stderr after expansion and before execution:

$> echo $listdir
+ echo ls
ls

$> $listdir
+ ls
file_0 file_1

As you can see, in the second line, bash will attempt to run the command ls just as if you have explicity called ls or even /usr/bin/ls

Edit

Expansion isn't the first step in in shell evaluation, see @Gordon Davisson's comment for details

1 Comment

Correction: expanding variables isn't the first thing the shell does. Most importantly, it comes after the shell parses things like quotes and escapes, command delimiters (;, &, etc), and redirects (>, <, etc), so if you include one of those in a variable, it won't be recognized. So you can store simple commands in variables, but not complex ones. And it's generally considered a bad idea anyway; variables are for data, not executable code. See BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.