List Info

Thread: basename is not working as expected if invoked in `` inside a find subcommand




basename is not working as expected if invoked in `` inside a find subcommand
country flaguser name
United States
2007-04-09 08:52:35
Hi, I have the following task: there are two directories and
some of files
in them differ. I try to show a list of files which differ
it in the
following way:
> find dir1 -exec diff -q "{}" dir2/`basename
{}` ;
or
> find dir1 -exec sh -c "diff -q {} dir2/`basename
{}`" ;

but for some reason basename doesn't strip the dir1 prefix
from the file
names, e.g. for
> find dir1 -exec echo `basename {}` ;
it just shows all the files as dir1/file1... .
Only
> find dir1 -exec basename {} ;
shows them correctly stripped of the directory name.

Has someone an idea why this happens?

Regards,
Andreas


Re: basename is not working as expected if invoked in `` inside a find subcommand
user name
2007-04-09 10:40:56
"Andreas R." <newsgroups2005geekmail.de> wrote:
>> find dir1 -exec diff -q "{}"
dir2/`basename {}` ;

Here, the command substitution is expanded by the shell
before find
runs.  basename sees the literal argument {}, and so it
outputs {},
and find sees dir2/{}.

>> find dir1 -exec sh -c "diff -q {}
dir2/`basename {}`" ;

Here, agin, the command substitution is expanded before find
runs.
Double quotes don't prevent an inner command substitution
from being
expanded.  Single quotes will, though.  This will do what
you want:

find dir1 -exec sh -c 'diff -q {} dir2/`basename {}`' ;

But if the filename contains any whitespace or shell
metacharacters,
it'll cause trouble.  You can protect against that like
this:

find dir1 -exec sh -c 'diff -q "$0"
dir2/"`basename "$0"`"' {} ;


paul



Re: basename is not working as expected if invoked in `` inside a find subcommand
country flaguser name
United States
2007-04-10 08:06:19
Paul Jarc wrote:
>>> find dir1 -exec diff -q "{}"
dir2/`basename {}` ;
> 
> Here, the command substitution is expanded by the shell
before find
> runs.  basename sees the literal argument {}, and so it
outputs {},
> and find sees dir2/{}.
> 
>>> find dir1 -exec sh -c "diff -q {}
dir2/`basename {}`" ;
> 
> Here, agin, the command substitution is expanded before
find runs.
> Double quotes don't prevent an inner command
substitution from being
> expanded.  Single quotes will, though.  This will do
what you want:
> 
> find dir1 -exec sh -c 'diff -q {} dir2/`basename {}`'
;
That works. Thanks a lot for the advice and explanation,
Paul.

> But if the filename contains any whitespace or shell
metacharacters,
> it'll cause trouble.  You can protect against that like
this:
> 
> find dir1 -exec sh -c 'diff -q "$0"
dir2/"`basename "$0"`"' {} ;
Wow. Rewritten in the form
  find dir1 -type f -exec sh -c 'echo "{}"
dir2/"`basename "{}"`"' ;
it works, but I still don't understand completely why it
works.
The first part "{}" is clear (I think), but how do
we get
to "`basename "{}"`" ? What is the
reason why "`basename {}`" doesn't work?
And where do you learn such tricks from? 
Is there a book you would suggest (or was reading the man
page enough)?

Regards,
Andreas


Re: basename is not working as expected if invoked in `` inside a find subcommand
country flaguser name
Germany
2007-04-09 16:54:59
Paul Jarc wrote:
>>> find dir1 -exec diff -q "{}"
dir2/`basename {}` ;
>
> Here, the command substitution is expanded by the shell
before find
> runs.  basename sees the literal argument {}, and so it
outputs {},
> and find sees dir2/{}.
>
>>> find dir1 -exec sh -c "diff -q {}
dir2/`basename {}`" ;
>
> Here, agin, the command substitution is expanded before
find runs.
> Double quotes don't prevent an inner command
substitution from being
> expanded.  Single quotes will, though.  This will do
what you want:
>
> find dir1 -exec sh -c 'diff -q {} dir2/`basename {}`'
;
That works. Thanks a lot for the advice and explanation,
Paul.

> But if the filename contains any whitespace or shell
metacharacters,
> it'll cause trouble.  You can protect against that like
this:
>
> find dir1 -exec sh -c 'diff -q "$0"
dir2/"`basename "$0"`"' {} ;
Wow. Rewritten in the form
  find dir1 -type f -exec sh -c 'echo "{}"
dir2/"`basename "{}"`"' ;
it works, but I still don't understand completely why it
works.
The first part "{}" is clear (I think), but how do
we get to "`basename "{}"`"
? What is the reason why "`basename {}`" doesn't
work? And where do you learn
such tricks from? 
Is there a book you would suggest (or was reading the man
page enough)?

Regards,
Andreas



Re: basename is not working as expected if invoked in `` inside a find subcommand
user name
2007-04-10 14:44:16
"Andreas R." <newsgroups2005geekmail.de> wrote:
>   find dir1 -type f -exec sh -c 'echo "{}"
dir2/"`basename "{}"`"' ;
> it works, but I still don't understand completely why
it works.

Actually, it still won't work in some cases.  If a filename
contains a
double quote, like 'foo" "bar', the shell will see
this command for
-c:
  echo "foo" "bar" dir2/"`basename
"foo" "bar"`"
which isn't what you want.  This will handle any flename
properly:
  find dir1 -exec sh -c 'diff -q "$0"
dir2/"`basename "$0"`"' {} ;

The difference here is that {} is substituted by find,
before sh is
invoked, so if {} appears within the -c command, sh will
interpret any
special characters in the filename as shell syntax, not as
part of the
filename.  Keeping {} as a separate argument to sh, and
referring to
it as a variable from within the command, prevents any such
problems.

> And where do you learn such tricks from? 

Experience, mostly.


paul



[1-5]

about | contact  Other archives ( Real Estate discussion Medical topics )