|
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 |
  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 |

|
2007-04-09 10:40:56 |
"Andreas R." <newsgroups2005 geekmail.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 |
  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 |
  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 |

|
2007-04-10 14:44:16 |
"Andreas R." <newsgroups2005 geekmail.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 )
|