I want to write a cleanup routine for my make file that removes every thing except the necessary source files in my folder. For example, my folder contains files with the following extensions: .f .f90 .F90 .F03 .o .h .out .dat .txt .hdf .gif.
I know I can accomplish this with:
find . -name ( '*.o' '*.out' '*.dat' '*.txt' '*.hdf' '*.gif' ) -delete
Using negation, I can do this:
find . -not -name '*.f*' -not -name '*.F*' -not -name '*.h' -delete
But, when I try to do this:
find . -not -name ( '*.f*' '*.F*' '*.h' )
I get an error:
find: paths must exceed expression: [first expression in the above list]
(In this case, I would get:
find: paths must exceed expression: *.f*
)
Can you explain why this happens, and how to do what I am trying to do? I just hate writing -not -name every time I want to add a file extension to the list. Also, I want to find out why this is giving me an error so that I can learn Linux better.
Thanks!
Advertisement
Answer
find . -not -name ( '*.f' '*.F' '*.h' )
is interpreted as
find . # path to search -not # negate next expression -name ( # expression for files named "(" '*.f' '*.F' .'*.h' ) # more paths to search?
leading to the error.
Since these are single-letter extensions, you can collapse them to a single glob:
find . -not -name '*.[fFh]'
but if they are longer, you have to write out the globs
find . -not -name '*.f' -not -name '*.F' -not -name '*.h'
or
find . -not ( -name '*.f' -o -name '*.F' -o -name '*.h' )
or switch to using regular expressions.
find . -not -regex '.*.(f|F|h)$'
Note that regular expressions in find
is not part of the POSIX standard and might not be available in all implementations.