GNU bug report logs -
#14023
dirname/basename unexpected results when run by xargs -I
Previous Next
Full log
View this message in rfc822 format
[Message part 1 (text/plain, inline)]
On 03/21/2013 08:52 PM, Juho-Pekka Kuitunen wrote:
> On Fri, Mar 22, 2013 at 3:05 AM, Bob Proulx <bob <at> proulx.com> wrote:
>> Juho-Pekka Kuitunen wrote:
>>> Reproduce example;
>>> $ echo "testdir/testfile" | xargs -I '{}' echo '{}', dir: $(echo dirname '{}') = $(dirname '{}')
>> The problem is the $(...) which is running the dirname during the
>> earlier shell command line parsing pass and passing the result off to
>> the xargs command.
>
> So if I understand correctly, subshell replacements gets executed
> before xargs fills in the replacements? I tried to rule out this
> wonkyness with the "$(echo '{}')" bit and it seemed to work in the
> correct order. The echo should produce an empty string if the subshell
> was evaluated too soon?
If you want to see when the shell is evaluating $(), use 'set -vx':
$ set -vx
$ echo testdir/testfile | xargs -I '{}' echo '{}', dir: $(echo dirname
'{}') = $(dirname '{}')
echo testdir/testfile | xargs -I '{}' echo '{}', dir: $(echo dirname
'{}') = $(dirname '{}')
+ echo testdir/testfile
echo dirname '{}')
dirname '{}')
echo dirname '{}')
echo dirname '{}'
++ echo dirname '{}'
dirname '{}')
dirname '{}'
++ dirname '{}'
+ xargs -I '{}' echo '{},' dir: dirname '{}' = .
testdir/testfile, dir: dirname testdir/testfile = .
$ set -
set -
+ set -
What you seem to want to do is invoke a shell instance on each file
name; that would be done as follows:
$ echo testdir/testfile | xargs -I {} sh -c \
'echo "$1", dir: $(echo dirname "$1") = $(dirname "$1")' sh {}
testdir/testfile, dir: dirname testdir/testfile = testdir
Or again with shell tracing (note there are two levels of shells - the
shell that spawns xargs, and the shell that xargs spawns, so I'm posting
two different traces):
$ set -vx
$ echo testdir/testfile | xargs -I {} sh -c 'echo "$1", dir: $(echo
dirname "$1") = $(dirname "$1")' sh {}
echo testdir/testfile | xargs -I {} sh -c 'echo "$1", dir: $(echo
dirname "$1") = $(dirname "$1")' sh {}
+ xargs -I '{}' sh -c 'echo "$1", dir: $(echo dirname "$1") = $(dirname
"$1")' sh '{}'
+ echo testdir/testfile
testdir/testfile, dir: dirname testdir/testfile = testdir
$ set -
set -
+ set -
$ echo testdir/testfile | xargs -I {} sh -cvx 'echo "$1", dir: $(echo
dirname "$1") = $(dirname "$1")' sh {}
echo "$1", dir: $(echo dirname "$1") = $(dirname "$1")
echo dirname "$1")
echo dirname "$1"
++ echo dirname testdir/testfile
dirname "$1")
dirname "$1"
++ dirname testdir/testfile
+ echo testdir/testfile, dir: dirname testdir/testfile = testdir
testdir/testfile, dir: dirname testdir/testfile = testdir
By the way, your question is mostly related to shell, and a bit with
xargs, and practically nothing to do with dirname. Your confusion on
WHEN $() is expanded would apply no matter what executable you plug in
instead of dirname. But since neither sh nor xargs belongs to
coreutils, you might get better answers by asking on a general forum on
shell programming subtleties.
>
> Very much possibly not a bug but I'm not 100% convinced yet. I've been
> chuckling at this all evening, love a good brain teaser even if it
> turns out to be something I overlooked instead of a bug. :-)
Hopefully shell tracing has managed to convince you.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[signature.asc (application/pgp-signature, attachment)]
This bug report was last modified 12 years and 64 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.