LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Distributions > Slackware
User Name
Password
Slackware This Forum is for the discussion of Slackware Linux.

Notices



Reply
 
Search this Thread
Old 12-26-2012, 12:01 AM   #1
narke
Member
 
Registered: Apr 2010
Posts: 70

Rep: Reputation: 0
'find': filter out subdirectories


Hi,

A question about 'find' command.

Suppose I have a tree, which contains subdirectories named from 'a' to 'z'. Under 'a', there is second level of subdirectories named from 'a1' to 'a100'.

Now I want a full list of files that reside in directories of a2 or [b-z], so I come up with the following command:

$ find . -path "./a/*" ! -path "./a2/*" -prune -o -type f -o -print.

But it doesn't work, everything under 'a' (including 'a2') disappeared from the output, that is not what I expected.

What's wrong with my command line?

Thanks in advance.

-woody
 
Old 12-26-2012, 04:32 AM   #2
gnashley
Amigo developer
 
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,775

Rep: Reputation: 481Reputation: 481Reputation: 481Reputation: 481Reputation: 481
'-maxdepth' is the option you want.
 
Old 12-26-2012, 03:14 PM   #3
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950
Here are a couple of good links about using find:
http://mywiki.wooledge.org/UsingFind
http://www.grymoire.com/Unix/Find.html

The basic syntax of a find command is like this:
Code:
find <starting dirs> <global options> <matching expressions> <actions> [-a/-o <matching expressions> <actions>]
There can be multiple entries for all of these.

One thing to understand about -prune is that it's an action. That is, it removes from consideration all the files matched by the expressions in front of it. So to fully use it, you also need to include a second expression that does what you want with the rest of the files.

A second thing to watch out for is that the default action (print) only works if there's a single matching expression to operate on. When you have multiple sets of matching expressions, each one must have its actions explicitly provided, and generally grouped with \(..\) brackets (see the last section of my first link).

So what you really want is something more like this:
Code:
find . ! \( -path "*/a2/*" -prune \) -o \( -type f -print \)
Although actually I don't think even this is necessary for most of your needs. Since it all comes down to a properly matching -path expression anyway, just use that directly:

Code:
find . -type f -path "*/a2/*" -print
find . -type f -path "./[b-z]/* -print
Be aware that some options like -name and -path use globbing patterns, while others like -regex use regular expressions. Check the find man page.

Last edited by David the H.; 12-26-2012 at 03:18 PM. Reason: minor edits
 
Old 12-26-2012, 10:49 PM   #4
narke
Member
 
Registered: Apr 2010
Posts: 70

Original Poster
Rep: Reputation: 0
Hi, please see my commands inline:

Quote:
Originally Posted by David the H. View Post
Here are a couple of good links about using find:
http://mywiki.wooledge.org/UsingFind
http://www.grymoire.com/Unix/Find.html

The basic syntax of a find command is like this:
Code:
find <starting dirs> <global options> <matching expressions> <actions> [-a/-o <matching expressions> <actions>]
There can be multiple entries for all of these.

One thing to understand about -prune is that it's an action. That is, it removes from consideration all the files matched by the expressions in front of it. So to fully use it, you also need to include a second expression that does what you want with the rest of the files.

A second thing to watch out for is that the default action (print) only works if there's a single matching expression to operate on. When you have multiple sets of matching expressions, each one must have its actions explicitly provided, and generally grouped with \(..\) brackets (see the last section of my first link).

So what you really want is something more like this:
Code:
find . ! \( -path "*/a2/*" -prune \) -o \( -type f -print \)
David, this is totally wrong. It will give me all the files which have "/a2/" in their name.
It is wrong because:
1, it won't list files such as b/x/y since there is not '/a2/' in the name;
2, it won't list files such as a/a2/dir/foo, since the '-prune' stops at 'a/a2/dir'.


Although actually I don't think even this is necessary for most of your needs. Since it all comes down to a properly matching -path expression anyway, just use that directly:

Code:
find . -type f -path "*/a2/*" -print
find . -type f -path "./[b-z]/* -print
I am looking for single command line solution because I need to redirect the output to a pipe.

Be aware that some options like -name and -path use globbing patterns, while others like -regex use regular expressions. Check the find man page.

Last edited by narke; 12-26-2012 at 10:50 PM.
 
Old 12-26-2012, 10:52 PM   #5
narke
Member
 
Registered: Apr 2010
Posts: 70

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by gnashley View Post
'-maxdepth' is the option you want.
Hi, gnashly,

I don't see why '-maxdepth' has anything to do with my problem. Can you explain a little in further? Thanks.
 
Old 12-26-2012, 11:20 PM   #6
Loomx
Member
 
Registered: Sep 2012
Distribution: Slackware
Posts: 30

Rep: Reputation: Disabled
Can you just combine the last two lines that David the H gave you?

Code:
find . \( -path './a/a2/*' -o -path './[b-z]/*' \) -type f -print

Last edited by Loomx; 12-27-2012 at 05:22 PM. Reason: Edited path to /a2/
 
Old 12-27-2012, 05:07 PM   #7
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950Reputation: 1950
Again, try to take the time to understand how the programs work. As pointed out, you can combine test expressions with grouping brackets.


On a higher level, you can combine the output of multiple commands in your shell through several different types of command grouping.

Code:
# With command grouping brackets
{
	find . -type f -path "*/a2/*" -print
	find . -type f -path "./[b-z]/*" -print
} | output_command


# With a subshell
(
	find . -type f -path "*/a2/*" -print
	find . -type f -path "./[b-z]/*" -print
) | output_command


# With process substitution
output_command < <(
	find . -type f -path "*/a2/*" -print
	find . -type f -path "./[b-z]/*" -print
	)

# With a function
findfiles(){

	for pattern; do
		find . -type f -path "$pattern" -print
	done

} | output_command

findfiles '*/a2/*' './[b-z]/*' | output_command
Of course the output will be simply that of the separate commands, one after the other, unless you insert some way to sort it manually.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Find directories that have two subdirectories in them-- PLEASE help pierceogden Programming 6 04-06-2012 09:47 PM
How can I find all directories with subdirectories with find? Ujjain Linux - Software 1 06-11-2011 06:57 PM
find command on subdirectories grob115 Linux - General 3 03-08-2011 11:43 AM
[SOLVED] Find not searching subdirectories JosephS Linux - Software 6 07-12-2010 11:16 PM
Evolution can't find libs in its own subdirectories slackist Linux - Software 3 03-16-2005 10:49 AM


All times are GMT -5. The time now is 11:51 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration