Search code examples
shellsu

Properly quote args for calling su -c


su -c takes a single string argument, that is passed to $SHELL -c. This makes running more complex commands a quoting nightmare if done by hand. What I would like: A function to turn "$@" into one string, that is parsed by the target shell appropiately. For simplicity lets either assume the target shell is the same as the current shell, or a simple (b)ash.

# Naive implementation:
run_su() {
  /bin/sh -c "$*"
  # To emulate su targetuser -c
}
run_su echo "double  spaces"
# Output: double spaces
# NOte the missing double space

I know sudo will do this the right way. But I don't want to depend on sudo unless we absolutely have to.

# This does the right thing
run_sudo() {
    sudo -u targetuser "$@"
}
run_sudo echo "double  spaces"

Solution

  • If you can assume bash, it's simple:

    /bin/bash -c "$(printf "%q " "$@")"
    

    For POSIX sh:

    quote() {
      for arg
      do
        var=$(printf "%sx" "$arg" | sed -e "s/'/'\\\\''/")
        var=${var%x}
        printf "'%s' " "$var"
      done
    }
    /bin/sh -c "$(quote "$@")"