查找具有特定模式的文件并忽略其他模式

查找具有特定模式的文件并忽略其他模式

我有这样的文件:

1_script1.sql
2_script2.sql
script1.sql
script2.sql

我想find仅用于获取文件1_script1.sql,并2_script2.sql使用文件的所有者来过滤它们。

find . -type f -user oracle -name "\{1..99\}_test*.sql"

答案1

find所使用的模式是简单的 shell glob 模式,其中只有,和被识别(并且作为转义运算符)。即使是一些实现所支持的(以不兼容的方式)也没有数字范围运算符。-name-path?*[...]\-regexfind

要使用基本 glob 模式以 1 或 2 位数字表示从 1 到 99 的数字,您需要[1-9]or [0-9][0-9](假设 C 区域设置[0-9]与 相同[0123456789]并接受具有任意字节值的文件名)并排除00,因此:

LC_ALL=C find . '(' -name '[1-9]_test*.sql' -o \
                    -name '[0-9][0-9]_test*.sql' \
                ')' ! -name '00_*' -type f -user oracle

-name首先进行检查,因为它们比需要或可能需要检索文件元数据的检查更便宜-type-user某些find实现在内部进行重新排序作为优化)

或者您可以使用zshwho 的 glob 具有<x-y>小数整数数字范围运算符并支持递归 globbing 和 glob 限定符:

print -rC1 -- **/<1-100>_test*.sql(NDn.u[oracle])

(这里允许数字 1 到 100 以任意位数表示,例如000023_testing.sql; 并且您可以获得排序(带有 的数字n)作为奖励,尽管您可以使用限定符禁用它oN)。

另一种方法是使用perl's File::Find

perl -MFile::Find -le '
  @user = getpwnam "oracle" or die "oracle user unknown\n";
  find(sub {
         if (/^(\d+)_test.*\.sql\z/s && $1 >= 1 && $1 <= 100) {
           if (@s = lstat$_) {
             print "File::Find::name if -f _ && $s[4] == $user[2];
           } else {warn "$_: $!\n"}
         }
       }, @ARGV)' -- .

相关内容