GNU bug report logs - #14023
dirname/basename unexpected results when run by xargs -I

Previous Next

Package: coreutils;

Reported by: Juho-Pekka Kuitunen <artanicus <at> mythmardyl.org>

Date: Fri, 22 Mar 2013 00:37:04 UTC

Severity: normal

Tags: moreinfo

Done: Bob Proulx <bob <at> proulx.com>

Bug is archived. No further changes may be made.

Full log


Message #16 received at 14023 <at> debbugs.gnu.org (full text, mbox):

From: Eric Blake <eblake <at> redhat.com>
To: Juho-Pekka Kuitunen <artanicus <at> mythmardyl.org>
Cc: 14023 <at> debbugs.gnu.org, Bob Proulx <bob <at> proulx.com>
Subject: Re: bug#14023: dirname/basename unexpected results when run by xargs
	-I
Date: Thu, 21 Mar 2013 21:11:09 -0600
[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.