Question

My Script:

#!/bin/bash

generic()
{

    echo $1;
    $1 > temp.txt 2>&1
}

generic "echo asd > /dev/null 2>&1; echo temp"

Expected Result:

  1. "asd" should go to /dev/null
  2. "temp" should go into temp.txt file.

Actual result:

  1. "asd > /dev/null 2>&1; echo temp" goes into temp.txt file.

Why only first echo statement runs and its output is getting redirect to temp.txt. Also, why is the second command treated as string?

Était-ce utile?

La solution

You need to read the spec

(This is the POSIX sh spec, because bash has no real spec. bash tries to be compatible to the POSIX sh, but adds a crapload of unnecessary complexity. You should use #!/bin/sh instead as a beginner and whenever you want to write a sane script)

In particular, you can't store anything other than a single command in a variable. If you execute from a variable as you do by saying $1, then this is interpreted as a single command:

Splitting occurrs on whitespace or whatever is inside the IFS variable. In you example, this result in the following token list:

  1. echo
  2. asd
  3. >
  4. /dev/null
  5. 2>&1;
  6. echo
  7. temp

This list is then executed as a process, equivalent to writing in C execlp("echo", "echo", "asd", ">", "/dev/null", "2>&1;", "echo", "temp", NULL);.

Note that if you had written "$1" instead, this would result in the shell trying to launch a program called echo asd > /dev/null 2>&1; echo temp with no arguments.

If you instead want to re-evaluate a string as a shell command line, you need to use eval: eval "$1". But be aware of the security implications! Eval is by many considered evil.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top