0

I wrote some code a while ago, and stored it in main.c. I then compiled it to test, and left it for a month or so while I waited for a use case to run my test.

This is a shared server, so things get moved around. The parent directory has a lot of other main.c and a lot of other test files, so what I'm looking for is a directory that contains both main.c and test. I can filter from there if there's a few results

Is this doable with mlocate/find? I could write something with sed to truncate the directory returned by find, and then run that through another iteration of find, but I'd prefer if there's a built-in solution that I can trust.

1 Answers1

1

With mlocate

This works in my Kubuntu:

mlocate -b --regex '^(main.c|test)$' | sed 's|/[^/]*$||' | sort | uniq -d

(tested with mlocate 0.26).

Note: this does not scale. If you want to find directories with three (or more) known files then you need to replace uniq -d with something more sophisticated (uniq -dc is a good start).


With find

This solution is relatively slow but does not rely on mlocate which is not portable.

Basic solution that tests directories for existence of two regular files with known names:

find / -type d -exec test -f {}/main.c \; -exec test -f {}/test \; -print

Note: this scales well. Adding few more tests for more names is trivial.

And to clarify: in test -f {}/test the first test is the standard utility named test (a.k.a. [), it has nothing to do with your test. If you named the file test1 then the snippet would be test -f {}/test1.

POSIX specification of find requires its -exec primary to substitute one {} that appears as a separate argument. Substituting more than one {} or substituting {} being only a part of an argument (like in {}/main.c) is allowed but not required. Therefore the above command may or may not work with your find (it works with GNU find for sure). Below is a fully portable (but slower) alternative:

find / -type d -exec sh -c 'test -f "$1/main.c" && test -f "$1/test"' find-sh {} \; -print

(find-sh is explained here: What is the second sh in sh -c 'some shell code' sh?).

When starting from / you probably want to exclude /proc, /sys, and /dev:

find / -type d \( -path /proc -o -path /sys -o -path /dev \) -prune -o \
       -exec test -f {}/main.c \; -exec test -f {}/test \; -print

If you want to implement more advanced exclusions/inclusions then please see Recursively search files with exclusions and inclusions and my answer there.

If your test supports -O (to test if the file is effectively owned by you) then consider test -O instead of test -f. This way you won't find somebody else's files. Notes:

  • test from GNU Coreutils does support -O.
  • test run directly from find -exec is a standalone executable (it may be the GNU test) but test run from sh may be a shell builtin which is different. To run the executable specify its full path (e.g. /usr/bin/test).