0

I write up a little shell script in bash that allows me to execute commands in sub-directories. Here is the script

bat.sh:

#!/bin/sh

for d in */; do
  echo "Executing \"$@\" in $d"
  cd $d
  `$@`
  cd ..
done

With my following directory structures

/home/user
--a/
----x.txt
----y.txt
--b/
----u.txt
----v.txt

I expect the following command to list out the content of directories a and b when it is executed in the home directory bat.sh ls

The result is

Executing "ls" in a/
/home/user/bin/bat.sh: line 6: x.txt: command not found
Executing "ls" in b/
/home/user/bin/bat.sh: line 6: u.txt: command not found

Any idea on what is going wrong here?

Hillman Li
  • 63
  • 5

1 Answers1

4

You don't want the back quotes; you want double quotes.

#!/bin/sh

for d in */
do
    echo "Executing \"$*\" in $d"
    (cd "$d" && "$@")
done

You are trying to execute the output of the command you pass, whereas you simply want to execute the command.

The use of an explicit subshell (the ( … ) notation) may avoid some problems with symlinks that jump to other directories. It is, in my (perhaps archaic) view, a safer way to switch directories for the purposes of executing commands.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • In this case, the missing quotes really are critical -- directories with spaces in their names are a thing that happen. – Charles Duffy Jun 08 '15 at 03:07
  • @CharlesDuffy: Yes; this time you're correct (but I was copying the code from the question which mostly worked). It is also an opportunity to legitimately use `$*` inside the double quotes, but maybe that's a bit subtle. – Jonathan Leffler Jun 08 '15 at 03:26
  • (Might also be good practice to make it `cd "$d" && "$@"`, to ensure that a failure in the `cd` doesn't result in running the wrapped command in the current directory; preferring graceful failure modes, &c). – Charles Duffy Jun 08 '15 at 03:31
  • Now that we are on the topic, Please check this answer: [Why should eval be avoided in Bash, and what should I use instead](http://stackoverflow.com/a/17529221/793796) Section "Execute output of a command". I have commented on that answer; but did not receive any satisfactory answer... – anishsane Jun 08 '15 at 06:37