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 #19 received at 14023 <at> debbugs.gnu.org (full text, mbox):

From: Juho-Pekka Kuitunen <artanicus <at> mythmardyl.org>
To: Eric Blake <eblake <at> redhat.com>
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: Sat, 23 Mar 2013 13:03:11 +0200
On Fri, Mar 22, 2013 at 5:11 AM, Eric Blake <eblake <at> redhat.com> wrote:
> 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.
>

Yup, that did the trick. Looks like I didn't understand the way xargs
works nearly well enough. Thanks for the lesson, my bad!

> --
> Eric Blake   eblake redhat com    +1-919-301-3266
> Libvirt virtualization library http://libvirt.org
>



--
Juho-Pekka Kuitunen




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.