0

I ran into the following problem:

user@machine:/$ echo ./dir/fil | xargs -I {} bash -c "echo $(basename {})"
./dir/fil

Why is it not just printing fil?

So basename seems to get the expected parameter ./dir/fil but somehow assumes it is all the filename. Conversly when used with dirname it only prints out .. It feels as if the /s are somehow escaped.

Why do I care?

I actually need to run something like this:

find -name "*.foo" | xargs -I {} bash -c "cd $(dirname \"{}\"); thirdpartytool $(basename \"{}\") 2>&1 > /dev/null | sort"
  • I need a non-zero return code if any call of thirdpartytool returns one, so find ... -exec ... does not work for me.
  • I need output redirection (discard stdout and sort stderr) so I need to call another shell.
  • I need to cd because thirdpartytool must be called from the directory where the file is, so I need dirname and basename in a subshell.

1 Answer 1

2
echo ./dir/fil | xargs -I {} bash -c "echo $(basename {})"

Here $(basename {}) is double-quoted and therefore it gets expanded by the current shell before xargs even runs. The output from basename {} is {}, so the command becomes:

echo ./dir/fil | xargs -I {} bash -c "echo {}"

It would be different if you single-quoted the shell code. Still embedding {} in shell code is wrong. You should pass the result of expansion of {} as positional parameter(s).

Eventually you want to use find. The truly robust command will be in a form of find … -print0 | xargs -0 … (if supported) or find … -exec ….

If I understand your goal right, your command will be like:

find . -name "*.foo" -print0 \
| xargs -0 -L1 sh -c 'cd "$(dirname "$1")" && thirdpartytool "$(basename "$1")" 2>&1 >/dev/null | sort' sh

where

  • I fixed the quoting,
  • I made sure the thirdpartytool runs only if cd succeeds,
  • I used sh because there is nothing specific to Bash in the shell code.

Additional notes:

1
  • Thanks! Not only do I have a working command now but I also learned a lot! Commented May 12, 2022 at 20:17

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.