Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot access 2>&1: How to treat variable content as a redirection not as filename

How can I control process output redirection based on variable content? I have tried following but it treats content of $redirect as a file name instead of redirection itself.

$ redirect="2>&1 >/dev/null"
$ ls -la $redirect
ls: cannot access 2>&1: No such file or directory
$ redirect=""
$ ls -la $redirect
total 376
drwx------ 1 wakatana users   4096 Feb  5 15:32 .
drwx------ 1 wakatana users   4096 Feb  2 18:44 ..
-rw------- 1 wakatana users    390 Feb  5 13:34 .bashrc
like image 989
Wakan Tanka Avatar asked Feb 12 '23 00:02

Wakan Tanka


2 Answers

Here's a way to achieve what you want, provided you accept to change the order of your command: use an alias. Aliases are usually frowned upon, and, as stated in the Bash manual, For almost every purpose, aliases are superseded by shell functions.

It seems we're here in the almost breach:

$ alias redirect='2>&1 > /dev/null'
$ redirect ls
$

And no eval.

like image 101
gniourf_gniourf Avatar answered Feb 13 '23 13:02

gniourf_gniourf


The ls error happens because the shell scans for redirections before it performs parameter expansion (and you might think about the sequence of redirections as well) and tries to list two files named 2>&1 and >/dev/null, much like if you had typed ls '2>&1' '>/dev/null'. The way to do what you want is to have a second iteration of all the redirections and substitutions. The eval builtin does just that:

 eval ls -la $redirect

If you must know, the order according to the POSIX shell specification is

  1. The words that are recognized as variable assignments or redirections according to Shell Grammar Rules are saved for processing in steps 3 and 4.

  2. The words that are not variable assignments or redirections shall be expanded. If any fields remain following their expansion, the first field shall be considered the command name and remaining fields are the arguments for the command.

  3. Redirections shall be performed as described in Redirection.

  4. Each variable assignment shall be expanded for tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal prior to assigning the value.

Here's an example with a less complex redirection to illustrate what is going on:

$ redirect=">file"
$ echo foo $redirect
foo >file
$ eval echo foo $redirect
$ cat file
foo

As Etan points out, eval may not be a suitable solution if you don't control the exact contents of redirect. Imagine what redirect='; rm -rf $HOME' can do.

like image 42
Jens Avatar answered Feb 13 '23 12:02

Jens