Quantcast
Channel: User Kamil Maciorowski - Super User
Viewing all articles
Browse latest Browse all 656

Answer by Kamil Maciorowski for In `find`, after using a test like `-type d`, how can I at some point undo this setting, so the rest evaluates as if `-type d` wasn't there?

$
0
0

If your find is GNU find then it supports -true which always evaluates as true and -false which always evaluates as false. Then this is what you can do:

# with GNU findfind . -type d -exec echo DIR: \; -false -o -print

The first part is -type d -exec echo DIR: \; -false, it echoes DIR: iff the current file is of the type directory. The trailing -falseguarantees this part fails; it will fail even if -type d evaluates to true. In other words there is no way for this part to succeed, because the only way for it to succeed is to evaluate -type d to true and -exec echo DIR: to true and-false to true. But -false cannot evaluate to true, ever.

The part preceding -o always fails, therefore -print will be evaluated for each and every file, as if -type d wasn't there.

POSIX-ly you can use -exec false \; for -false and -exec true \; for -true.

# POSIX-lyfind . -type d -exec echo DIR: \; -exec false \; -o -print

In this case you can avoid spawning false as an additional process. Use this trick:

# POSIX-lyfind . -type d -exec echo DIR: \; ! -type d -o -print

Again, the part before -o cannot be true (-type d and ! -type d cannot both be true), this guarantees the desired logic. The snippet ! -type d -o is equivalent to what you used in the question (! is a portable equivalent of -not), there is nothing wrong with it.

Note the trick requires you to negate some previous test, while -exec false \; is universal. -false is also universal but your find may or may not support it. If your find supports -false and if portability is not an issue, then just use -false -o as shown at the beginning of this answer; this is the simplest solution.

There is another way to avoid spawning true and/or false processes. -name '*' is a test that always succeeds, so it may be treated as a POSIX equivalent of -true. Similarly you can use ! -name '*' for -false. The downside is -name '*' kinda obfuscates the code, it does not reveal its purpose; it looks like a remnant of some old -name test with a meaningful pattern that evolved to *, now like something that can (and should) be removed from the command. -true or -exec true \; are way less confusing.


Viewing all articles
Browse latest Browse all 656

Trending Articles