Finding files in the filesystem

Status
Not open for further replies.

diskdiddler

Wizard
Joined
Jul 9, 2014
Messages
2,377
I'm reading some documentation and I'll be damned if I can get the find command to work for me.

Let's say I know I have a directory something like this
/mnt/array/media/pics/holidays/hawaii/fun.jpg
and this
/mnt/array/media/pics/holidays/spain/fun.jpg

I specifically want to find ALL folders which contain the words "array" and "pics" in the path (I just do, ok, sorry)

I've tried the following, doesn't seem to work
find / -name '*array*pics*'
find / -name 'array*pics*'
find / -name '*array*pics*.*'
find / -path '*array*pics*'
find / -name 'array*pics*'
find / -name '*array*pics*.*'

I'll be damned if I know what I'm doing wrong here, anyone got some tips?
 

jgreco

Resident Grinch
Joined
May 29, 2011
Messages
18,680
# find / -print | egrep 'array.*pics'

That assumes that "array" comes first.

For your specific case, though, it seems like

# find /mnt/array -name '*pics*' -type d -print

would work (but it will also find directories named "tropics" ...
 

diskdiddler

Wizard
Joined
Jul 9, 2014
Messages
2,377
Thank you, let me just double down on it actually though...


I want to find this for example.
all paths containing "edia" and "pain" in any part of them
So it would catch
/mnt/array/media/pics/holidays/spain/fun.jpg
It would also catch
/mnt/array/data/media/pics/horrible-stuff/pain/oh-golly.jpg


Just hypothetically? I want a good, thorough catch all.
Would I be right thinking I just need '*edia.*pain' ? or
'*edia*.*pain*' ?
etc
 

jgreco

Resident Grinch
Joined
May 29, 2011
Messages
18,680
The problem here is that you were thinking "find" applies the -name to the entire resulting string. It does not; it looks at the labels ("filenames" or "directorynames") that it is traversing.

So when you use "-name '*foo*'" thast means that it will match any label that matches *foo* by simple shell-style globbing (only * ? [ and ] allowed). So it will match /mnt/afooa/name (more on this in a bit) or /mnt/name/foo; the "*" allows zero-or-more characters to match. You can limit it to directories with "-type d" or files with "-type f".

If you look at what "find" does when it runs across the filesystem, it is actually only looking at the label as it traverses. So going back to my example immediately above, when it is looking at the specific file "/mnt/afooa/name", what ACTUALLY matches is "/mnt/afooa" and that's what it prints, as it traverses that label. As it descends into that directory, it is looking at the labels within the directory, so it prints "/mnt/afooa" but not "/mnt/afooa/name".

Okay so far? "find -name" traverses the filesystem and only matches the string after the trailing slash. However it will traverse the intermediate directories in the process.

But you're interested in the pathname, so that's a little more crappy. And your requirement for "in any part of them" says, to me, "in either order."

So it isn't clear that find - at least by itself - is the correct tool. We can use grep, but grep uses regular expressions, not shell globbing. Your examples in post #3 confuse the two of those. Thast won't work.

It's pretty easy to create a regular expression that searches for one string, any arbitrary cruft in between, and then another. That's "onestring.*another"; where the "." means "matches any character" and "*" means "zero or more of them". That matches "onestringanother", "onestring and another", etc. But only with egrep, where you're supplying a regular expression.

But that doesn't solve an ordering problem. You can handle the ordering problem within a single regexp but it isn't simple for a n00b to grasp the syntax. Instead, you can use grep (egrep not needed) twice:

# find / -print | grep "edia" | grep "pain"

is probably the most trivially understandable solution to the problem of finding a pathname that contains both "edia" and "pain" anywhere on the system.

The shell is very powerful and chaining together different commands until you get exactly what you need can be a lot of fun.
 

jgreco

Resident Grinch
Joined
May 29, 2011
Messages
18,680
I'm kind of surprised no one tried to show me up with "find / -path '*edia*' -path '*pain*' -print"
 

fracai

Guru
Joined
Aug 22, 2012
Messages
1,212
I'm kind of surprised no one tried to show me up with "find / -path '*edia*' -path '*pain*' -print"
I was about to just now... :smile:

I think you could even get away with:

find / -path '*edia*pain*'

But, that excludes cases where "edia" comes after "pain". You could handle this with a regex, but now you've got 100 problems.
 

jgreco

Resident Grinch
Joined
May 29, 2011
Messages
18,680
But, that excludes cases where "edia" comes after "pain". You could handle this with a regex, but now you've got 100 problems.

The whole problem with trying to use a regex is that you rapidly get out of "a relative beginner could trivially understand this" territory.
 
Status
Not open for further replies.
Top