Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Strange behaviuor of "find" [SOLVED]
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Other Things Gentoo
View previous topic :: View next topic  
Author Message
gsoe
Apprentice
Apprentice


Joined: 10 Dec 2006
Posts: 284
Location: Denmark

PostPosted: Tue Mar 19, 2013 1:33 pm    Post subject: Strange behaviuor of "find" [SOLVED] Reply with quote

Hi!

After 10 years using linux I still happen to stumble upon things that baffle me.
Can anyone explain this behaviuor:
Code:
serv2 ~ # ls /etc | grep ^env
env.d
environment
serv2 ~ # find /etc -name env*
/etc/environment
/etc/env.d

But then:
Code:
serv2 ~ # ls /etc | grep gru
grub.d
serv2 ~ # find /etc -name grub*
serv2 ~ # find /etc -name 'grub*'
/etc/grub.d
/etc/default/grub
/etc/portage/package.keywords/grub

Greetings gsoe


Last edited by gsoe on Tue Mar 19, 2013 3:53 pm; edited 1 time in total
Back to top
View user's profile Send private message
gsoe
Apprentice
Apprentice


Joined: 10 Dec 2006
Posts: 284
Location: Denmark

PostPosted: Tue Mar 19, 2013 1:59 pm    Post subject: Reply with quote

The plot thickens:
Code:
serv2 ~ # find /etc -name grub*
serv2 ~ # cd /etc/
serv2 etc # find /etc -name grub*
/etc/grub.d
serv2 etc # find /etc -name 'grub*'
/etc/grub.d
/etc/default/grub
/etc/portage/package.keywords/grub
serv2 etc #
Back to top
View user's profile Send private message
eyoung100
Veteran
Veteran


Joined: 23 Jan 2004
Posts: 1411

PostPosted: Tue Mar 19, 2013 2:08 pm    Post subject: Reply with quote

It might help you get the answer you expect if you were to add the trailing /
Code:
ls etc | grep gru
find /etc/ grub*


From the find man page:
Quote:
-name pattern
Base of file name (the path with the leading directories removed) matches shell pattern pattern. The metacharacters ('*', '?', and '[]') match a '.' at the start of the base name (this is a change in findutils-4.2.2; see section STANDARDS CONFORMANCE below). To ignore a directory and the files under it, use -prune; see an example in the description of -path. Braces are not recognised as being special, despite the fact that some shells including Bash imbue braces with a special meaning in shell patterns. The filename matching is performed with the use of the fnmatch(3) library function. Don't forget to enclose the pattern in quotes in order to protect it from expansion by the shell.


GNU Grep 2.14
GNU Find
_________________
The Birth and Growth of Science is the Death and Atrophy of Art -- Unknown
Registerd Linux User #363735
Adopt a Post | Strip Comments| Emerge Wrapper


Last edited by eyoung100 on Tue Mar 19, 2013 2:19 pm; edited 1 time in total
Back to top
View user's profile Send private message
gsoe
Apprentice
Apprentice


Joined: 10 Dec 2006
Posts: 284
Location: Denmark

PostPosted: Tue Mar 19, 2013 2:19 pm    Post subject: Reply with quote

The trailing slash doesn't seem to make any difference:
Code:
serv2 ~ # find /etc/ -name grub*
serv2 ~ # find /etc/ -name 'grub*'
/etc/grub.d
/etc/default/grub
/etc/portage/package.keywords/grub
serv2 ~ #
Omitting the "-name" option
Code:
serv2 ~ # find /etc/ grub*
just returns hundreds of false positives, in fact about everything in /etc.
Back to top
View user's profile Send private message
py-ro
Veteran
Veteran


Joined: 24 Sep 2002
Posts: 1511
Location: St. Wendel

PostPosted: Tue Mar 19, 2013 3:06 pm    Post subject: Reply with quote

if you write
Code:
find -name foo*
the * will be interpreted by your shell.
Back to top
View user's profile Send private message
gsoe
Apprentice
Apprentice


Joined: 10 Dec 2006
Posts: 284
Location: Denmark

PostPosted: Tue Mar 19, 2013 3:16 pm    Post subject: Reply with quote

Hi py-ro!

I see. So in the case of
Code:
find /etc -name 'foo*'
the "find" command will interpret the expression?
But then again, why do
Code:
serv2 ~ # find /etc -name grub*
serv2 ~ # find /etc -name env*
/etc/environment
/etc/env.d
serv2 ~ #
behave differently? A shell problem?
Greetings gsoe.
Back to top
View user's profile Send private message
py-ro
Veteran
Veteran


Joined: 24 Sep 2002
Posts: 1511
Location: St. Wendel

PostPosted: Tue Mar 19, 2013 3:23 pm    Post subject: Reply with quote

You can view which expand it will do.

Position your cursor after env* and press
Code:
CTRL+x g
atleast in Basc.
Back to top
View user's profile Send private message
gsoe
Apprentice
Apprentice


Joined: 10 Dec 2006
Posts: 284
Location: Denmark

PostPosted: Tue Mar 19, 2013 3:50 pm    Post subject: Reply with quote

Hi py-ro and eyoung100

Thanks for the pointer to the man excerpt and the bit about the shell expansion. Nifty little trick. I get the expected results, when my cwd is /etc:
Code:
serv2 etc # grub*
grub.d/
serv2 etc # env*
env.d/       environment 
But apparently something about letting the shell expand expressions for find is confusing the find command:
Code:
serv2 etc # find /etc -name gru*
/etc/grub.d
serv2 etc # find /etc -name env*
find: paths must precede expression: environment
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
serv2 etc # find /etc -name envi*
/etc/environment
serv2 etc #
I'll regard the subject as solved and abandon my former sloppy use of find.

Greetings gsoe
Back to top
View user's profile Send private message
khayyam
Advocate
Advocate


Joined: 07 Jun 2012
Posts: 2248

PostPosted: Tue Mar 19, 2013 5:11 pm    Post subject: Reply with quote

gsoe wrote:
But apparently something about letting the shell expand expressions for find is confusing the find command

gsoe ... find expects '-name' to be a pattern, eg, 'pat*', but if its expanded by the shell it becomes multiple 'pat patter patterns'. The 'find' manpage states "[p]lease note that you should quote patterns as a matter of course, otherwise the shell will expand any wildcard characters in them." So, its not really confused, it just expects 'pat*' to be a pattern and not a string of space delimited words.

best ... khay
Back to top
View user's profile Send private message
gsoe
Apprentice
Apprentice


Joined: 10 Dec 2006
Posts: 284
Location: Denmark

PostPosted: Tue Mar 19, 2013 5:36 pm    Post subject: Reply with quote

Hi khay

Thank you for the elaboration. So really
Code:
serv2 etc # find /etc -name env*
find: paths must precede expression: environment
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
doesn't work because the shell expansion returns a string of space delimited words, namely
Code:
env.d/       environment
while
Code:
serv2 etc # find /etc -name envi*
/etc/environment
does work because there's only one instance of a word in the expansion.

I have to admit that when I read the "-name" section in the man pages years ago, I must have memorised something like like "omit the quotes if it works without them". Luckily I haven't run into any disasters because of it!

Greetings gsoe.
Back to top
View user's profile Send private message
khayyam
Advocate
Advocate


Joined: 07 Jun 2012
Posts: 2248

PostPosted: Tue Mar 19, 2013 7:36 pm    Post subject: Reply with quote

gsoe ...

yes, so its like passing a sentence rather than a pattern. It really just depends on how the shell treats meta characters.

Code:
# echo $SHELL
/bin/zsh
# find /etc -name env{*}
/etc/environment
/etc/env.d
/etc/portage/env
# print -rl /etc/**/env*
/etc/env.d
/etc/environment
/etc/portage/env

best ... khay
Back to top
View user's profile Send private message
Akkara
Administrator
Administrator


Joined: 28 Mar 2006
Posts: 5284
Location: &akkara

PostPosted: Tue Mar 19, 2013 8:23 pm    Post subject: Reply with quote

gsoe wrote:
So really find /etc -name env* doesn't work because the shell expansion returns a string of space delimited words ... while find /etc -name envi* does work because there's only one instance of a word in the expansion.

That's correct.

Best usage for find is to always include quotes in patterns, that way you're not relying on the luck of directory contents as to whether it works or not. Also, (in case you weren't aware), there's a difference between single quotes and double quotes. Check the documentation or ask here if you need that cleared up.

Also: omission of quotes exposes a possible vulnerability if the directory is world-writable that someone could stick extra files in there just to mess this up. Alas there's a lot of these sorts of hiccups in shell. It's easy to get started and write something quick but it's a lot harder to make sure all pathological cases are adequately covered.

Oh, one final thought/trick: Put echo in front of a command line to see what the command that gets issued looks like after the shell's done it's magic. As in, echo find /etc -name env*.
_________________
echo 'long long long x;' | gcc -x c -c -
Back to top
View user's profile Send private message
gsoe
Apprentice
Apprentice


Joined: 10 Dec 2006
Posts: 284
Location: Denmark

PostPosted: Tue Mar 19, 2013 8:59 pm    Post subject: Reply with quote

Hi again

Quote:
Best usage for find is to always include quotes in patterns
That's exactly my conclusion! I've just realised the reason for some of the behaviour was:
Quote:
the luck of directory contents as to whether it works or not
It also seems that cached contents of the shell has some influence on what happens.

@khay; I've noticed that some experienced users (while hardly any inexperienced) use zsh. Maybe time has come to look into it.

Thanks again! gsoe
Back to top
View user's profile Send private message
khayyam
Advocate
Advocate


Joined: 07 Jun 2012
Posts: 2248

PostPosted: Tue Mar 19, 2013 10:27 pm    Post subject: Reply with quote

gsoe wrote:
@khay; I've noticed that some experienced users (while hardly any inexperienced) use zsh. Maybe time has come to look into it.

gsoe ... well, zsh is a 'bourne' shell, and though it uses some ksh idioms, there is nothing that would cause a bash user to wonder ... if you switched tommorow you probably wouldn't notice the difference.

Its not *just* for experienced users :) ... there are just many interactive features that make it a pleasure to use, eg,

Code:
# for i (*.txt) mv $i ${i/.txt/.sh}
# zmv '(*).sh' '$1.txt'

In the former the 'for i in <condition> ; do <command> ; done' is simplified, and the latter is just a better way to do the former .... and reverses it :)

See:
A User's Guide to the Z-Shell
The Zshell Guide
Zsh Documentation
zsh-lovers (app-shells/zsh-lovers)

best ... khay
Back to top
View user's profile Send private message
eyoung100
Veteran
Veteran


Joined: 23 Jan 2004
Posts: 1411

PostPosted: Tue Mar 19, 2013 10:37 pm    Post subject: Reply with quote

just a hunch that last script takes all the files ending in .txt and renames them to files ending in sh, and thats a lot easier to read 8)
_________________
The Birth and Growth of Science is the Death and Atrophy of Art -- Unknown
Registerd Linux User #363735
Adopt a Post | Strip Comments| Emerge Wrapper
Back to top
View user's profile Send private message
gsoe
Apprentice
Apprentice


Joined: 10 Dec 2006
Posts: 284
Location: Denmark

PostPosted: Tue Mar 19, 2013 10:53 pm    Post subject: Reply with quote

I see. Some extended commands that'll make life easier, if you really use your shell. If you don't know them well, the bash way might be easier to understand.

Greetings. gsoe
Back to top
View user's profile Send private message
khayyam
Advocate
Advocate


Joined: 07 Jun 2012
Posts: 2248

PostPosted: Tue Mar 19, 2013 11:09 pm    Post subject: Reply with quote

eyoung100 wrote:
just a hunch that last script takes all the files ending in .txt and renames them to files ending in sh, and thats a lot easier to read 8)

eyoung100 ... yes, thats what the first command, the 'for', does, and the second 'zmv' reverses the the outcome of the previous command.

gsoe wrote:
Some extended commands that'll make life easier, if you really use your shell. If you don't know them well, the bash way might be easier to understand.

gsoe ... I don't see that at all ... there is 'familarity' involved whether it is bash or zsh.

best ... khay
Back to top
View user's profile Send private message
gsoe
Apprentice
Apprentice


Joined: 10 Dec 2006
Posts: 284
Location: Denmark

PostPosted: Tue Mar 19, 2013 11:22 pm    Post subject: Reply with quote

Well, yes I guess so. The first one I could immediately understand by familiarity with bash :-), the second one I wouldn't have guessed without seeing the first. Anyhow, as soon as you've seen the "zmv" command once, you probably won't forget it again.
As for myself, it may be harder to remember the syntax of the bash "for i in... do... done" command. Whenever I use it, I always make it do something innocent like "echo" the result. Just to make sure...

Greetings gsoe
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Other Things Gentoo All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum