181

I'm running the find command to find certain files, but some files in sub-directories have the same name which I want to ignore.

I'm interested in files/patterns like this:

/dev/abc-scanner, /dev/abc-cash ....

The command:

find /dev/ -name 'abc-*'

What's being returned:

/dev/abc-scanner
/dev/abc-cash
...
...
...
/dev/.udev/names/abc-scanner
/dev/.udev/names/abc-cash

I want to ignore the latter files: /dev/.udev/...

alex
  • 6,818
  • 9
  • 52
  • 103
suffa
  • 3,606
  • 8
  • 46
  • 66

6 Answers6

293

If you just want to limit the find to the first level you can do:

 find /dev -maxdepth 1 -name 'abc-*'

... or if you particularly want to exclude the .udev directory, you can do:

 find /dev -name '.udev' -prune -o -name 'abc-*' -print
Mark Longair
  • 446,582
  • 72
  • 411
  • 327
  • If I wanted to list where all the above symlinks pointed to found in the above pattern, would I just use a pipe? Something like find /dev -maxdepth 1 -name 'abc-*' | ls -l – suffa Oct 10 '11 at 16:11
  • 2
    It's better to use `xargs` instead, so something like: `find /dev -maxdepth 1 -name 'abc-*' | xargs ls -l` but if there's any chance that they will have whitespace in the names, you should do `find /dev -maxdepth 1 -name 'abc-*' -print0 | xargs -0 ls -l` – Mark Longair Oct 10 '11 at 16:17
  • However, as [Stephen Darlington's answer points out](http://stackoverflow.com/questions/7715485/how-to-only-find-files-in-a-given-directory-and-ignore-subdirectories-using-bash/7715550#7715550), I'm not sure why you wouldn't just do `ls -l /dev/abc-*` – Mark Longair Oct 10 '11 at 16:19
  • Also, if you want to find out where symlinks point to, you can do `for x in /dev/abc-*; do readlink -f $x; done` – Mark Longair Oct 10 '11 at 16:28
  • 2
    Or if you want subdirectories only on the first level, `ls -l /dev/abc-* /dev/*/abc-* | fgrep -v /dev/.udev` ... except at least on my Linux `/dev/*/*` does not include files in `/dev/.udev/*` so you can omit the `fgrep -v`. – tripleee Oct 10 '11 at 16:29
  • The `-maxdepth` argument is a "global" option, so you must specify it before the other options (as shown above) or you'll get a warning message. – Dave Aug 03 '22 at 18:05
13

Is there any particular reason that you need to use find? You can just use ls to find files that match a pattern in a directory.

ls /dev/abc-*

If you do need to use find, you can use the -maxdepth 1 switch to only apply to the specified directory.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Stephen Darlington
  • 51,577
  • 12
  • 107
  • 152
  • I think you mean `-maxdepth 1` rather than `-maxdepth 0` – Mark Longair Oct 10 '11 at 16:04
  • 5
    It should be pointed out that the wildcard is the important part here, not `ls`. You can find the same files with `echo` or `wc` or what have you, because the shell expands the wildcard for you. So `for file in /dev/abc-*; do something with each "$file"; done` might be what the OP is actually looking for. – tripleee Oct 10 '11 at 16:11
  • 1
    Ah, I can never remember which way round it is... Thanks for the edit. Also, worth noting that it's not universal. The Solaris version of `find` doesn't have it for example. – Stephen Darlington Oct 10 '11 at 16:11
  • @tripleee +1. Yup. Doing it all in the shell would be preferable if possible. – Stephen Darlington Oct 10 '11 at 16:13
  • Also if there are subdirectories named `abc-*` you will get the wrong result from `ls -l`, but perhaps `ls -ld` is acceptable as a workaround. – tripleee Oct 10 '11 at 16:32
  • If you need to process the files returned by ls, you can use a for loop. For example: `for f in \`ls /dev/abc-*\`; do echo $f; done` – Mustafa Ozturk Aug 26 '16 at 13:57
  • @MustafaOzturk As tripleee notes, you don't need the ls in back ticks. The shell expands the wildcard, so the ls is superfluous. – Stephen Darlington Aug 26 '16 at 14:19
  • @StephenDarlington backticks are needed for the for loop example that I gave. Without it bash treats ls as a item in a list. `for f in ls; do echo $f; done` just prints 'ls' (tested on Solaris) (Nevermind, just saw the original answer) – Mustafa Ozturk Aug 26 '16 at 19:32
  • 1
    @MustafaOzturk The `ls` is superfluous. `for f in abc*; ...` is all you need. – Stephen Darlington Aug 26 '16 at 19:35
  • 1
    ls does not work well when there are too many files in the directory. – Philippe Delteil Mar 06 '19 at 14:07
5

This may do what you want:

find /dev \( ! -name /dev -prune \) -type f -print
Chris J
  • 30,688
  • 6
  • 69
  • 111
4

I got here with a bit more general problem - I wanted to find files in directories matching pattern but not in their subdirectories.

My solution (assuming we're looking for all cpp files living directly in arch directories):

find . -path "*/arch/*/*" -prune -o -path "*/arch/*.cpp" -print

I couldn't use maxdepth since it limited search in the first place, and didn't know names of subdirectories that I wanted to exclude.

S. Kaczor
  • 401
  • 3
  • 8
2

There is an alternative to find called rawhide (rh) and it's much easier to use. Instead of:

find /dev -maxdepth 1 -name 'abc-*'

You can do:

rh -r /dev '"abc-*"'

The -r is the same as "-m1 -M1" which is the same as find's "-mindepth 1 -maxdepth 1", just a lot shorter.

Rawhide (rh) is available from https://raf.org/rawhide or https://github.com/raforg/rawhide. It works at least on Linux, FreeBSD, OpenBSD, NetBSD, Solaris, macOS, and Cygwin.

Disclaimer: I am the current author of rawhide

raf
  • 43
  • 5
0
find /dev -maxdepth 1 -name 'abc-*'

Does not work for me. It return nothing. If I just do '.' it gives me all the files in directory below the one I'm working in on.

find /dev -maxdepth 1 -name "*.root" -type 'f' -size +100k -ls

Return nothing with '.' instead I get list of all 'big' files in my directory as well as the rootfiles/ directory where I store old ones.

Continuing. This works.

find ./ -maxdepth 1 -name "*.root" -type 'f' -size +100k -ls
564751   71 -rw-r--r--   1 snyder   bfactory   115739 May 21 12:39 ./R24eTightPiPi771052-55.root
565197  105 -rw-r--r--   1 snyder   bfactory   150719 May 21 14:27 ./R24eTightPiPi771106-2.root
565023   94 -rw-r--r--   1 snyder   bfactory   134180 May 21 12:59 ./R24eTightPiPi77999-109.root
719678   82 -rw-r--r--   1 snyder   bfactory   121149 May 21 12:42 ./R24eTightPiPi771098-10.root
564029  140 -rw-r--r--   1 snyder   bfactory   170181 May 21 14:14 ./combo77v.root

Apparently /dev means directory of interest. But ./ is needed, not just .. The need for the / was not obvious even after I figured out what /dev meant more or less.

I couldn't respond as a comment because I have no 'reputation'.

aifrim
  • 555
  • 9
  • 20
  • 1
    You gain reputation by giving good answers. Please read this https://stackoverflow.com/conduct – aifrim May 21 '20 at 23:10
  • There are reasons you aren't allowed to comment and that gives you no permission to put comments here in the Answer section. Please delete this. – Rob May 22 '20 at 02:06