1

I am trying to write a find command that finds both files and directories, the issue is that I get only files or an error depending on certain variables in the command.

This command outputs nothing at all:

find '/mnt/downloads/cache/' -depth -mindepth 1 \( -type f ! -exec fuser -s {} \; \) -o \( -type d -empty \) -print

This is because the two filters are not encapsulated in ( ). Why are double quotes needed?

This command outputs files only but not directories:

find '/mnt/downloads/cache/' -depth -mindepth 1 \( \( -type f ! -exec fuser -s {} \; \) -o \( -type d -empty \) \) -print

Extra set of brackets encapsulating the two arguments is the only difference.

The last variation of the command results in an error:

find '/mnt/downloads/cache/' -depth -mindepth 1 \( \( -type f ! -exec fuser -s {} \; \) -o \( -type d -empty {} \) \) -print

find: paths must precede expression: {}

Why does adding a second set of {} after diretory test results in this error?

Fixed command:

find "/mnt/downloads/cache" -depth -mindepth 1 \( \
-type f \! -exec fuser -s '{}' \; -o \
-type d \! -empty \) \
-print
2
  • 1
    Umm - doesn't it output twice because you are using both -print and -exec echo {} ? Why would you put the extra {} after -empty? AFAIK it doesn't take an argument, so that's why {} is being parsed as a misplaced path. Dec 9, 2017 at 13:43
  • @steeldriver You are right about print / echo, I though I had removed it. Edited question to remove that part. So you are saying that the {} is an argument of exec only and type d / f doesn't need {}? If so why am I still not getting directories in the output? Feel free to add it as an answer as I can't accept a comment no matter how correct it is :)
    – DominicM
    Dec 9, 2017 at 13:52

1 Answer 1

1

Since the implied and (-a) has higher precedence than the -o, the right hand side of the -o in the first expression is taken as one unit with regard to the or operation, i.e. this:

\( -type f ! -exec fuser -s {} \; \) -o \( -type d -empty \) -print

acts the same as this:

\( -type f ! -exec fuser -s {} \; \) -o \( -type d -empty -print \)

So for files, it runs fuser, and for directories it prints their names.


The second:

\( \( -type f ! -exec fuser -s {} \; \) -o \( -type d -empty \) \) -print

has explicit parenthesis, but you don't need the inner ones, this is equal:

\( -type f ! -exec fuser -s {} \;  -o  -type d -empty  \) -print

And it should print all empty directories and files for which fuser returns a falsy value (!= 0, inverted by the !).


In the third you have ... -empty {} ..., where the {} is taken as path name, and the error message tells what the issue is.

1
  • Ahh, what I wanted is ! -empty, I missed the not operator...
    – DominicM
    Dec 9, 2017 at 14:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .