Skip to main content
grammar tweaks
Source Link
Jeff Schaller
  • 68.8k
  • 35
  • 122
  • 267

the function run does not see > and dump.sql. That is probably not what you want because it prevents you from changing all the redirections with a single environment variable, as the output of echo "${@}" is redirected to the file then, too. Thus, you should use something like run --redirect dump.sql mysqldump blabla, see below.

  1. Stick with "$@" and use eval. This may take you to a quoting nightmare, of course. You have to quote everything except for the > so that the shell sees a bare > in the command line before it does quote removal.

  2. Handle the redirection seperatelyseparately:

    run --redirect dump.sql mysqldump blabla
    
    run() {
        if [ "$1" == '--redirect' ]; then
            shift
            redirect_target="$1"
            shift
        else
            redirect_target='/dev/stdout' # works at least with Linux
        fi
    
        if [[ "$(printenv DRY_RUN)" = "yes" ]]
        then
            echo "${@}"
        else
            "${@}" > "$redirect_target"
        fi
    }
    

the function run does not see > and dump.sql. That is probably not what you want because it prevents you from changing all the redirections with a single environment variable as the output of echo "${@}" is redirected to the file then, too. Thus you should use something like run --redirect dump.sql mysqldump blabla, see below.

  1. Stick with "$@" and use eval. This may take you to a quoting nightmare, of course. You have to quote everything except for the > so that the shell sees a bare > in the command line before it does quote removal.

  2. Handle the redirection seperately:

    run --redirect dump.sql mysqldump blabla
    
    run() {
        if [ "$1" == '--redirect' ]; then
            shift
            redirect_target="$1"
            shift
        else
            redirect_target='/dev/stdout' # works at least with Linux
        fi
    
        if [[ "$(printenv DRY_RUN)" = "yes" ]]
        then
            echo "${@}"
        else
            "${@}" > "$redirect_target"
        fi
    }
    

the function run does not see > and dump.sql. That is probably not what you want because it prevents you from changing all the redirections with a single environment variable, as the output of echo "${@}" is redirected to the file then, too. Thus, you should use something like run --redirect dump.sql mysqldump blabla, see below.

  1. Stick with "$@" and use eval. This may take you to a quoting nightmare, of course. You have to quote everything except for the > so that the shell sees a bare > in the command line before it does quote removal.

  2. Handle the redirection separately:

    run --redirect dump.sql mysqldump blabla
    
    run() {
        if [ "$1" == '--redirect' ]; then
            shift
            redirect_target="$1"
            shift
        else
            redirect_target='/dev/stdout' # works at least with Linux
        fi
    
        if [[ "$(printenv DRY_RUN)" = "yes" ]]
        then
            echo "${@}"
        else
            "${@}" > "$redirect_target"
        fi
    }
    
added 645 characters in body
Source Link
Hauke Laging
  • 94.8k
  • 21
  • 132
  • 185

An important point which I noticed after I published my answer: With a call like

run mysqldump blabla > dump.sql

the function run does not see > and dump.sql. That is probably not what you want because it prevents you from changing all the redirections with a single environment variable as the output of echo "${@}" is redirected to the file then, too. Thus you should use something like run --redirect dump.sql mysqldump blabla, see below.

There are two possibilities:

        if [[ "$(printenv DRY_RUN)" = "yes" ]]
        then
            if [ "$1" == '--redirect' ]; then
                # do not output "--redirect file"
                shift
                shift
            fi
            echo "${@}"
        else
            if [ "$1" == '--redirect' ]; then
                shift
                redirect_target="$1"
                shift
                "${@}" > "$redirect_target"
            else
                "${@}"
            fi
        fi

There are two possibilities:

        if [[ "$(printenv DRY_RUN)" = "yes" ]]
        then
            echo "${@}"
        else
            if [ "$1" == '--redirect' ]; then
                shift
                redirect_target="$1"
                shift
                "${@}" > "$redirect_target"
            else
                "${@}"
            fi
        fi

An important point which I noticed after I published my answer: With a call like

run mysqldump blabla > dump.sql

the function run does not see > and dump.sql. That is probably not what you want because it prevents you from changing all the redirections with a single environment variable as the output of echo "${@}" is redirected to the file then, too. Thus you should use something like run --redirect dump.sql mysqldump blabla, see below.

There are two possibilities:

        if [[ "$(printenv DRY_RUN)" = "yes" ]]
        then
            if [ "$1" == '--redirect' ]; then
                # do not output "--redirect file"
                shift
                shift
            fi
            echo "${@}"
        else
            if [ "$1" == '--redirect' ]; then
                shift
                redirect_target="$1"
                shift
                "${@}" > "$redirect_target"
            else
                "${@}"
            fi
        fi
added 1 character in body
Source Link
Hauke Laging
  • 94.8k
  • 21
  • 132
  • 185

You should use "${@}" instead of ${@} (like with echo "${@}") but that is not the reason for your problem.

The reason is that redirection takes places very early in command line parsing, before parameter substitution. Thus after the variable has put > in the command line, the shell is not looking for > any more.

There are two possibilities:

  1. Stick with "$@" and use eval and use . This may take you to a quoting nightmare, of course. You have to quote everything except for the eval>. This may take you to a quoting nightmare, of course. You have to quote everything except for the so that the shell sees a bare>>` so that the shell sees a bare > in the command line before it does quote removal.

  2. Handle the redirection seperately:

    run --redirect dump.sql mysqldump blabla
    
    run() {
        if [ "$1" == '--redirect' ]; then
            shift
            redirect_target="$1"
            shift
        else
            redirect_target='/dev/stdout' # works at least with Linux
        fi
    
        if [[ "$(printenv DRY_RUN)" = "yes" ]]
        then
            echo "${@}"
        else
            "${@}" > "$redirect_target"
        fi
    }
    

You can avoid the redirect_target='/dev/stdout' if you put the if [ "$1" == '--redirect' ] in the else branch of if [[ "$(printenv DRY_RUN)" = "yes" ]].

        if [[ "$(printenv DRY_RUN)" = "yes" ]]
        then
            echo "${@}"
        else
            if [ "$1" == '--redirect' ]; then
                shift
                redirect_target="$1"
                shift
                "${@}" > "$redirect_target"
            else
                "${@}"
            fi
        fi

You should use "${@}" instead of ${@} (like with echo "${@}") but that is not the reason for your problem.

The reason is that redirection takes places very early in command line parsing, before parameter substitution. Thus after the variable has put > in the command line, the shell is not looking for > any more.

There are two possibilities:

  1. Stick with "$@" and use eval. This may take you to a quoting nightmare, of course. You have to quote everything except for the >so that the shell sees a bare>` in the command line before it does quote removal.

  2. Handle the redirection seperately:

    run --redirect dump.sql mysqldump blabla
    
    run() {
        if [ "$1" == '--redirect' ]; then
            shift
            redirect_target="$1"
            shift
        else
            redirect_target='/dev/stdout' # works at least with Linux
        fi
    
        if [[ "$(printenv DRY_RUN)" = "yes" ]]
        then
            echo "${@}"
        else
            "${@}" > "$redirect_target"
        fi
    }
    

You can avoid the redirect_target='/dev/stdout' if you put the if [ "$1" == '--redirect' ] in the else branch of if [[ "$(printenv DRY_RUN)" = "yes" ]].

        if [[ "$(printenv DRY_RUN)" = "yes" ]]
        then
            echo "${@}"
        else
            if [ "$1" == '--redirect' ]; then
                shift
                redirect_target="$1"
                shift
                "${@}" > "$redirect_target"
            else
                "${@}"
            fi
        fi

You should use "${@}" instead of ${@} (like with echo "${@}") but that is not the reason for your problem.

The reason is that redirection takes places very early in command line parsing, before parameter substitution. Thus after the variable has put > in the command line, the shell is not looking for > any more.

There are two possibilities:

  1. Stick with "$@" and use eval. This may take you to a quoting nightmare, of course. You have to quote everything except for the > so that the shell sees a bare > in the command line before it does quote removal.

  2. Handle the redirection seperately:

    run --redirect dump.sql mysqldump blabla
    
    run() {
        if [ "$1" == '--redirect' ]; then
            shift
            redirect_target="$1"
            shift
        else
            redirect_target='/dev/stdout' # works at least with Linux
        fi
    
        if [[ "$(printenv DRY_RUN)" = "yes" ]]
        then
            echo "${@}"
        else
            "${@}" > "$redirect_target"
        fi
    }
    

You can avoid the redirect_target='/dev/stdout' if you put the if [ "$1" == '--redirect' ] in the else branch of if [[ "$(printenv DRY_RUN)" = "yes" ]].

        if [[ "$(printenv DRY_RUN)" = "yes" ]]
        then
            echo "${@}"
        else
            if [ "$1" == '--redirect' ]; then
                shift
                redirect_target="$1"
                shift
                "${@}" > "$redirect_target"
            else
                "${@}"
            fi
        fi
Source Link
Hauke Laging
  • 94.8k
  • 21
  • 132
  • 185
Loading