find without recursion - unix

Is it possible to use the find command in some way that it will not recurse into the sub-directories? For example,
DirsRoot
|-->SubDir1
| |-OtherFile1
|-->SubDir2
| |-OtherFile2
|-File1
|-File2
And the result of something like find DirsRoot --do-not-recurse -type f will be only File1, File2?

I think you'll get what you want with the -maxdepth 1 option, based on your current command structure. If not, you can try looking at the man page for find.
Relevant entry (for convenience's sake):
-maxdepth levels
Descend at most levels (a non-negative integer) levels of direc-
tories below the command line arguments. `-maxdepth 0' means
only apply the tests and actions to the command line arguments.
Your options basically are:
# Do NOT show hidden files (beginning with ".", i.e., .*):
find DirsRoot/* -maxdepth 0 -type f
Or:
# DO show hidden files:
find DirsRoot/ -maxdepth 1 -type f

I believe you are looking for -maxdepth 1.

If you look for POSIX compliant solution:
cd DirsRoot && find . -type f -print -o -name . -o -prune
-maxdepth is not POSIX compliant option.

Yes it is possible by using -maxdepth option in find command
find /DirsRoot/* -maxdepth 1 -type f
From the manual
man find
-maxdepth levels
Descend at most levels (a non-negative integer) levels of directories below the starting-points.
-maxdepth 0
means only apply the tests and actions to the starting-points themselves.

Related

How to generate a list of directories that has names starting with "A" and ending with "O"?

How do I use the find command to generate a list of directories whose names starts with "A" and ends with "O"?
The answer is
$ find . -type d -name "A*O"
The -type d option tells find to only output directory names, and the -name "A*O" option further restricts those names to those matching the pattern A*O (i.e. starting with A and ending with O). It does this in the current directory (.) and will recursively enter any directory therein and performs the same task.
You can use
Case Sensitive - find . -type d -name "AO" 2>/dev/null
Case Insensitive - find . -type d -iname "AO" 2>/dev/null
We can use -i to ignore the case.

Rename all subdirectories in csh shell

I'm using csh and I have a directory structure containing multiple sub-directories. I'm trying to rename all the directories and sub-directories but not the files inside these directories. So something like
From
topdir1
--dir11
--dir12
topdir2
--dir21
----dir211
--dir22
to
topdir1.test
--dir11.test
--dir12.test
topdir2.test
--dir21.test
----dir211.test
--dir22.test
I can list the directories with find . -maxdepth 3 -type d. I'm trying to use a foreach loop to rename them. So
foreach i (`find . -maxdepth 3 -type d`)
mv $i $i.test
end
But this doesn't work as once the top level directory is renamed, it cannot find the sub-directories, so it only renames the top level directories.
Any idea on how to go about this?
Thanks
How about reversing the find results so that the subdirectories are listed first?
foreach i (`find ./* -maxdepth 3 -type d | sort -r`)
mv $i $i.test
end
Sort will output the longest directory names last, using the -r (reverse) flag changes it so that the lowest directories will be listed first, and be renamed before their parent directories do.
Use the -depth option to find.
From the solaris man find page:
-depth Always true. Causes descent of the
directory hierarchy to be done so that
all entries in a directory are acted on
before the directory itself. This can
be useful when find is used with cpio(1)
to transfer files that are contained in
directories without write permission.
Why use a loop? Just let find do the work:
find . -depth -maxdepth 3 -type d -exec mv {} {}.test \;
That is not strictly portable (some implementations of find may legally not expand {}.test to the string you want, so you might prefer:
find . -depth -maxdepth 3 -type d -exec sh -c 'mv $0 $0.test' {} \;

Order of Parameters in find

Should it matter in which order you specify the criteria in a find command? On Solaris,
find /my/directory ! -type d -mtime -3 -ls
doesn't find directories, but
find /my/directory -mtime -3 -ls ! -type d
does. The man page seems to state that each primary is treated in isolation as a Boolean expression, and the results just ANDed together, and that the -ls primary is just one that happens always to return TRUE.
-ls is an action for find.
When you say:
find /my/directory -mtime -3 -ls ! -type d
the part after -ls is essentially ignored and you get the same results as you'd get by saying:
find /my/directory -mtime -3 -ls

find, excluding dir, not descending into dir, AND using maxdepth and mindepth

This is RHEL 5.6 and GNU find 4.2.27.
I am trying to exclude a directory from find, and want to make sure that directory isn't descended into. I've seen plenty of posts saying -prune will do this - and it does. I can run this command:
find . -type d -name "./.snapshot*" -prune -o -print
and it works. I run it through strace and verify it is NOT descending into .snapshot.
I also want to find directories ONLY at a certain level. I can use mindepth and maxdepth to do this:
find . -maxdepth 8 -mindepth 8 -type d
and it gives me all the dirs 8 levels down, including what's in .snapshot.
If I combine the prune and mindepth and maxdepth options:
find . -maxdepth 8 -mindepth 8 -type d \( -path "./.snapshot/*" -prune -o -print \)
the output is right - I see all the dirs 8 levels down except for what's in .snapshot, but if I run that find through strace, I see that .snapshot is still being descended into - to levels 1 through 8.
I've tried a variety of different combinations, moving the precedence parens around, reording expression components - everything that yields the right output still descends into .snapshot.
I see in the man page that -prune doesn't work with -depth, but doesn't say anything about mindepth and maxdepth.
Can anyone offer any advice?
Thanks...
Bill
I think this is your answer. -mindepth seems to turn off all test till that level. kind of a bummer.
(right from "man find")
-mindepth levels
**Do not apply any** tests or actions at levels less than levels (a non-negative integer).
'-mindepth 1' means process all files except the command line arguments.
I'm adding this as another answer because it's a different take on the issue. You could try the find command like this :
find * .[^s][^n]* (other switches/args)
It would avoid the .snapshot directory by using the shell instead of the find switches. granted it's not perfect but maybe it's close enough for what you are doing.

GNU find: Search in current directory first

how can I tell find to look in the current folder first and then continue search in subfolders? I have the following:
$ find . -iname '.note'
folder/1/.note
folder/2/.note
folder/3/.note
folder/.note
What I want is this:
$ find . -iname '.note'
folder/.note
folder/1/.note
folder/2/.note
folder/3/.note
Any ideas?
find's algorithm is as follows:
For each path given on the command line, let the current entry be that path, then:
Match the current entry against the expression.
If the current entry is a directory, then perform steps 1 and 2 for every entry in that directory, in an unspecified order.
With the -depth primary, steps 1 and 2 are executed in the opposite order.
What you're asking find to do is to consider files before directories in step 2. But find has no option to do that.
In your example, all names of matching files come before names of subdirectories in the same directory, so find . -iname '.note' | sort would work. But that obviously doesn't generalize well.
One way to process non-directories before directories is to run a find command to iterate over directories, and a separate command (possibly find again) to print matching files in that directory.
find -type d -exec print-matching-files-in {} \;
If you want to use a find expression to match files, here's a general structure for the second find command to iterate only over non-directories in the specified directory, non-recursively (GNU find required):
find -type d -exec find {} -maxdepth 1 \! -type d … \;
For example:
find -type d -exec find {} -maxdepth 1 \! -type d -iname '.note' \;
In zsh, you can write
print -l **/(#i).note(Od)
**/ recurses into subdirectories; (#i) (a globbing flag) interprets what follows as a case-insensitive pattern, and (Od) (a glob qualifier) orders the outcome of recursive traversals so that files in a directory are considered before subdirectories. With (Odon), the output is sorted lexicographically within the constraint laid out by Od (i.e. the primary sort criterion comes first).
Workaround would be find . -iname '.note' | sort -r:
$ find . -iname '.note' | sort -r
folder/.note
folder/3/.note
folder/2/.note
folder/1/.note
But here, the output is just sorted in reverse order and that does not change find's behaviour.
For me with GNU find on Linux I get both orderings with different test runs.
Testcase:
rm -rf /tmp/depthtest ; mkdir -p /tmp/depthtest ; cd /tmp/depthtest ; for dir in 1 2 3 . ; do mkdir -p $dir ; touch $dir/.note ; done ; find . -iname '.note'
With this test I get the poster's first result. Note the ordering of 1 2 3 .. If I alter this ordering to to . 1 2 3
rm -rf /tmp/depthtest ; mkdir -p /tmp/depthtest ; cd /tmp/depthtest ; for dir in . 1 2 3 ; do mkdir -p $dir ; touch $dir/.note ; done ; find . -iname '.note'
I get the poster's second result.
In either case adding -depth to find does nothing.
EDIT:
I wrote a perl oneliner to look in to this further:
perl -e 'opendir(DH,".") ; print join("\n", readdir(DH)),"\n" ; closedir(DH)'
And I ran this against /tmp/depthtest after running testcase 1 with these results:
.
..
1
2
3
.note
I ran it again after testcase 2 with these results:
.
..
.note
1
2
3
Which confirms that the results are in directory order.
The -depth option to find only controls whether e.g. ./1/.note is processed before or after ./1/, not whether ./.note or ./1/ is first, so the order of the results is purely based on directory order (which is mostly creation order).
It might be helpful to look at How do I recursively list all directories at a location, breadth-first? to learn how to work around this problem.
find -s . -iname ".note" doesn't help? or find . -iname '.note'|sort ?
Find in the current folder
find ./in_save/ -type f -maxdepth 1| more
==>73!

Resources