0

I want to have command that would execute command in arguments in dir1 and dir2

tests

# put this in our .bashrc
alias gca="git commit -v -a"

my-exec gca
my-exec gca -m "my commit wrapped in double quotes"
my-exec gca -m "my commit wrapped in double quotes with 'something' in single quotes"
my-exec gca -m 'my commit wrapped in single quotes with "something" in double quotes'

I have tried

my-exec () {
  (cd $HOME/dir1 && eval "$@")
  (cd $HOME/dir2 && eval "$@")
}

but it's not working, because

# working fine
my-exec gca

# executes
# gca -m my commit wrapped in double quotes
# actually
my-exec gca -m "my commit wrapped in double quotes"

# didnt try
my-exec gca -m "my commit wrapped in double quotes with 'something' in single quotes"

# didnt try
my-exec gca -m 'my commit wrapped in single quotes with "something" in double quotes'

UPDATE

also tried

my-exec () {
  echo "$@"      > /tmp/my-exec
  cat /tmp/my-exec
  (cd $HOME/dir1 && bash -i /tmp/my-exec)
  (cd $HOME/dir2 && bash -i /tmp/my-exec)
}

but echo "$@" too doesn't preserve quotes

5
  • 1
    Remove the eval. Commented Apr 1, 2019 at 18:30
  • Is the behavior different when you use eval $@ instead on eval "$@" ? Commented Apr 1, 2019 at 18:30
  • @akskap eval $@ is working the same as eval "$@", and thus not applicable to my use case Commented Apr 1, 2019 at 18:39
  • @choroba removing eval is not executing aliases and thus not applicable to my use case Commented Apr 1, 2019 at 18:46
  • 1
    Bash FAQ 050 is relevant, but start by replacing your alias with a function: gca () { git commit -v -a "$@"; }. That should at least allow cd ... && "$@" to work in my_exec. Commented Apr 1, 2019 at 19:16

1 Answer 1

4

Remove the eval -- it causes many parsing problems, and in this case you shouldn't need it:

my-exec () {
  (cd $HOME/dir1 && "$@")
  (cd $HOME/dir2 && "$@")
}

You might also run into trouble because gca is an alias, and they have a separate set of parsing oddities associated with them. Use a function instead. But be sure to remove the alias definition, or it'll override the function:

unalias gca
gca() {
    git commit -v -a "$@"
}

If you really really really need to keep gca as an alias rather than a function (why?), you will need to use eval, but in order to keep that from screwing up complex arguments, you need to re-quote those. Fortunately, you can use bash printf's %q format directive to add suitable quoting/escaping to the arguments:

my-exec () {
  (cd $HOME/dir1 && "$(printf '%q ' "$@")")
  (cd $HOME/dir2 && "$(printf '%q ' "$@")")
}

But really, you should use functions instead of aliases. They have much cleaner syntax and semantics, and (as we're seeing here) work in places where aliases don't.

Sign up to request clarification or add additional context in comments.

1 Comment

(cd $HOME/dir1 && eval "$(printf '%q ' "$@")") indeed working

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.