Find Command Include Sub Directory

This script writes the output files to FILES but I don't want to exclude all directories from ABC_CHQ and LYS_ADV, I want to include one sub directory name process which is under ABC_CHQ and LYS_ADV in the search. Right now its excluding everything from prune directories such as ABC_CHQ, LYS_ADV etc.

Please let me know how can I include only one sub directory which is under ABC_CHQ lets say.

FILES=`find /home/u10/payments -name "ABC_CHQ" -prune -o \
    -name "ABCD_CTRE" -prune -o -name "LYS_ADV" -prune -o -type f -mtime +$DAYS \
      -exec ls {} \;`
FILES=`find /home/u10/payments/ABC_CHQ  -type f -mtime +$DAYS -exec ls {} \;`

Try that.

Also please note that -o and -a require ( ) example:

find . \( name abc -o -name foo \) -mtime +10

Your code probably did not do what you expected.

Jim, code is working fine, tell me how to include one sub directory from the said directory.

Thanks

Your description of what you're trying to do leaves some requirements ambiguous. With lots of guessing, the following might come close to what you're trying to do:

FILES=$(find /home/u10/payments \
	/home/u10/payments/ABC_CHQ/subdir1 \
	/home/u10/payments/LYS_ADV/subdir2 \
	\( -name ABC_CHQ -prune \) -o \
	\( -name ABCD_CTRE -prune \) -o \
	\( -name LYS_ADV -prune \) -o \
	-type f -print)

It will store a list of regular files in and under /home/u10/payments , /home/u10/payments/ABC_CHQ/subdir1 , and /home/u10/payments/LYS_ADV/subdir2 while ignoring files in other subdirectories under /home/u10/payments/ABC_CHQ and /home/u10/payments/LYS_ADV , and all files under /home/u10/payments/ABCD_CTRE .

1 Like

Thanks a lot Don, Its working perfectly fine.

Trivial, but '-print' or '-exec ls {}' are usually unnecessary, as 'find' prints file names unless you tell it you want something else.

It might be easier to make a clone tree of the dirs you *do* want, once, and search in it. A clone tree can be built up using either symlinks to dirs or identically named dirs containing links to files. If you use sym links for files or dirs, the '-follow' is needed to make 'find' traverse them.

The -print is needed in this case because the directory names that have files under them pruned will be printed as part of the default case. Adding the explicit -print (or the MUCH less efficient and MUCH slower -exec ls {} \; ) in the case where we want the pathnames printed will avoid printing those unwanted directory names.

Isn't '-type f' enough to stop directory names?

In a directory where ls -l produces the output:

total 16
drwxr-xr-x  13 dwc  staff  442 Feb 11 15:04 payments
-rw-r--r--   1 dwc  staff  895 Feb 11 14:59 problem
-rwxr-xr-x   1 dwc  staff  212 Feb 11 16:06 tester

The commands:

find . -name payments -prune -type f
          and
find . \( -name payments -prune \) -type f

produce no output. (There is an implied AND operation between all of the subexpressions and there is no regular file named "payments"._ The command:

find . \( -name payments -prune \) -o -type f

produces the output:

./payments
./problem
./tester

But, the command:

find . \( -name payments -prune \) -o -type f -print

produces the output:

./problem
./tester

And, the command:

find . \( -name payments -prune -print \) -o -type f

produces the output:

./payments

With nothing that produces explicit output like -print anywhere in the expression, -print is supplied by default to each half of the OR ( -o ) in the expression. With any -print in the entire expression, an OR subexpression produces output only if there is an explicit element of that subexpression that prints output.

So the '-name <pattern> -prune' upsets the normal implicit '-print' because the '-name <pattern>' is false in the hit space, although the -prune inverts its meaning. Seems like a design error, that pruning should have not used '-name' but been a separate, unified peer option that returns false on a hit and also prevents descending. Too late now. POSIX did not see the incongruity, I guess. The art of UNIX shell still seems to be in knowing all the gotcha's. :smiley:

Not really. The thing that upset the normal default -print is that we have an -o binary primary and we only want to print the results from one of the subexpressions. (We don't want to print the names of the directories we have pruned on the left half of the OR, but we do want to print the regular files selected by the right half of the OR.) The POSIX standards documented existing practice; they did not invent new (even though possibly more intuitive) behavior for the find utility.

The behavior of the find -prune primary is described as:

	prune	The primary shall always evaluate as true; it shall cause find not to descend the
		current pathname if it is a directory. If the depth primary is specified, the prune
		primary shall have no effect.

And the way the standards describe when pathnames are printed by default is:

	If no expression is present, print shall be used as the expression. Otherwise, if the given
	expression does not contain any of the primaries exec, ok, or print, the given expression
	shall be effectively replaced by:
		( given_expression ) print

Personally, I think this is reasonable and rational behavior, but I agree that it is something that shell script programmer's have to learn and might not be intuitive until you do learn the details of how and when it works.