从bash shell中的find中排除文件扩展名列表

Tal*_*Tal 4 linux makefile find

我想为我的make文件编写一个清理例程,除了我文件夹中的必要源文件之外,它会删除所有内容.例如,我的文件夹包含具有以下扩展名的文件:.f .f90 .F90 .F03 .o .h .out .dat .txt .hdf .gif.

我知道我可以用以下方法完成此任务

find . -name \( '*.o' '*.out' '*.dat' '*.txt' '*.hdf' '*.gif' \) -delete
Run Code Online (Sandbox Code Playgroud)

使用否定,我可以这样做:

find . -not -name '*.f*' -not -name '*.F*' -not -name '*.h' -delete
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试这样做时:

find . -not -name \( '*.f*' '*.F*' '*.h' \)
Run Code Online (Sandbox Code Playgroud)

我收到一个错误:

find: paths must exceed expression: [first expression in the above list]
Run Code Online (Sandbox Code Playgroud)

(在这种情况下,我会得到: find: paths must exceed expression: *.f* )

你能解释为什么会这样,以及如何做我想做的事情?每次我想在列表中添加文件扩展名时,我都讨厌编写-not -name.另外,我想找出为什么这会给我一个错误,这样我就可以更好地学习Linux.

谢谢!

eph*_*ent 8

find . -not -name \( '*.f' '*.F' '*.h' \)
Run Code Online (Sandbox Code Playgroud)

被解释为

find
    .                      # path to search
    -not                   # negate next expression
    -name \(               # expression for files named "("
    '*.f' '*.F' .'*.h' \)  # more paths to search?
Run Code Online (Sandbox Code Playgroud)

导致错误.

由于这些是单字母扩展,您可以将它们折叠为单个glob:

find . -not -name '*.[fFh]'
Run Code Online (Sandbox Code Playgroud)

但如果它们更长,你必须写出全球

find . -not -name '*.f' -not -name '*.F' -not -name '*.h'
Run Code Online (Sandbox Code Playgroud)

要么

find . -not \( -name '*.f' -o -name '*.F' -o -name '*.h' \)
Run Code Online (Sandbox Code Playgroud)

或切换到使用正则表达式.

find . -not -regex '.*\.(f|F|h)$'
Run Code Online (Sandbox Code Playgroud)

请注意,正则表达式find不是POSIX标准的一部分,可能并非在所有实现中都可用.