Preserve Interpretation in Bash Variable

238 views Asked by At

I'm trying to Preserve Interpretation in Bash Variable.

Example

when I run the following line at command prompt.

rm aaa 2>> error_file ; echo '<br><br>' >> error_file

I get the following (which is what I want):

rm: cannot remove `aaa': No such file or directory

If I put the error handling code in a variable it blows-up.

ERROR_HAN="2>> error_file ; echo '<br><br>' >> error_file"
rm aaa $ERROR_HAN
rm: cannot remove `"2>>"': No such file or directory

I have tried quoting a number of ways but no luck. I can't seem to Preserve Interpretation for the 2>> portion of the variable.

3

There are 3 answers

2
devnull On

Use eval:

eval rm aaa ${ERROR_HAN}
3
user000001 On

Don't put the command in a variable. Use a function instead:

rm_error() {
    rm "$@" 2>> error_file 
    echo '<br><br>' >> error_file
}

rm_error file1 file2 file3

See also: BashFAQ/050: I'm trying to put a command in a variable, but the complex cases always fail!

6
konsolebox On

You'll to use eval for that which is unsafe.

Better redirect it on a block, and use process substitution:

{
    rm aaa
    # ... other commands
} 2> >(
    while read -r LINE; do
        echo "$LINE"
        echo '<br><br>'
    done >> error_file
)

Another way which would write <br><br> only once at the end:

{
    rm aaa
    # ... other commands
} 2> >(
    if read -r LINE; then
        while
            echo "$LINE"
            read -r LINE
        do
            continue
        done
        echo '<br><br>'
    fi >> error_file
)

This one would write <br><br> even without an error, and only once at the end:

{
    rm aaa
    # ... other commands
} 2>> error_file
echo '<br><br>' >> error_file

Note if you're only using one command like rm, you don't have to place it inside a block, just rm aaa 2>> >( .... And I think you'll only need one line:

rm aaa 2>> >(read -r LINE && echo "$LINE"$'\n''<br><br>' >> error_file)

Another:

EFILE=/path/to/error_file
rm aaa 2> >(read -r LINE && echo "$LINE"$'\n''<br><br>' >> "$EFILE")

Command-specific function:

EFILE=/path/to/error_file

function log_error_to_file {
    read -r LINE && echo "$LINE"$'\n''<br><br>' >> "$EFILE"
}

rm aaa 2> >(log_error_to_file)
another_command 2> >(log_error_to_file)

Multiple lines:

function log_error_to_file {
    while read -r LINE; do
        echo "$LINE"
        echo '<br><br>'
    done >> error_file
}