1

When using the command find, I often need to have a flow control, e.g. if .. then.

A simplified example;

find ~ -maxdepth 1 -type d -exec echo -e "\nnext beg of new dir::" \; -exec ls -lad \{\} \;

The test -type d returns true if current file is of the type directory, thus I see blank lines and the notice that a dir follows.

Yet I want the next -exec to show the output of ls for each file, directory or non-directory.

Using the option -o before the second -exec is not the solution. That inverts the flow control, the files which are not directories are listed. Like if giving -not -type d.

A solution seems to be when writing both options, -not -type d and -o, like this:

find ~ -maxdepth 1 -type d -exec echo -e "\nnext beg of new dir::" \; -not -type d -o -exec ls -lad \{\} \;

Is this the official way to "undo" -type d?

Anton Wessel
  • 161
  • 10
  • If you do not care about soft links, block, character devices just use -type f (what is not dir is file) – Romeo Ninov Dec 11 '23 at 18:58
  • == 13.12.2023 22:33 thanks and excuse me, that was my typo. I have forgotton to type "-type d" on both locations when I was typing my post by hand. Now what to do: if I edit and correct my post would be good for future readers, but your hint will become non-understandable. Regards – Anton Wessel Dec 13 '23 at 21:33
  • Don't worry. I have sorted this out. – Kamil Maciorowski Dec 14 '23 at 08:26

1 Answers1

1

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 find
find . -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 -false guarantees 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-ly
find . -type d -exec echo DIR: \; -exec false \; -o -print

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

# POSIX-ly
find . -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.

  • == 13.12.23 22:45 many thanks for your answer. You confirm that my logic was correct (which was my petition), and your "false" is better. Tanks and Regards. – Anton Wessel Dec 13 '23 at 21:53