I am trying to automatically create symlinks to directories and to replace a certain text string (foo) of the original name in the link name (bar). The name of the target directories may contain spaces (e.g. "foo with whitespace").
This is a minimal example:
> ls -Q
"foo"
"foo with whitespace"
I am trying the following command (using xargs' -p option to debug/check the result before its execution):
find . -iname "*foo*" -print0 | xargs -0 -I '{}' -p ln -s {} `echo {} | sed -e s#foo#bar#g
My desired outcome is this:
ln -s 'foo with whitespace' 'bar with whitespace'
ln -s 'foo' 'bar'
However the string replacement fails. The actual output looks like this:
ln -s './foo with whitespace' './foo with whitespace'?...
ln -s ./foo ./foo?...
If I use constant strings instead of {}, the string replacement works as intended:
find . -iname "*foo*" -print0 | xargs -0 -I '{}' -p ln -s {} `echo "foo" | sed -e s#foo#bar#g`
ln -s './foo with whitespace' bar?...
ln -s ./foo bar?...
What's my mistake and how do I fix the command invocation?
Edit: Tilman Schmidt's solution works like a charm.
Best Answer
The command substitution
is performed only once, before the pipeline composed of the
find
andxargs
commands is run. Sosed
gets the string{}
as input and, not findingfoo
, outputs it unchanged. Then the shell runs the resulting command lineSo command substitution is the wrong tool here. Try something like
(untested) instead. Note that this won't work if you have filenames containing newlines.