Find

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

  • September 8, 2022

我有如下文件:

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

我想find只用來獲取文件1_script1.sql2_script2.sql並使用文件的所有者來過濾它們。

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

和使用find的模式是簡單的 shell glob 模式,其中只有,被辨識(並且作為轉義運算符)。即使一些實現支持(以不兼容的方式)也沒有數字範圍運算符。-name``-path``?``*``[...]``\``-regex``find

要使用基本 glob 模式以一位或 2 位數字表示從 1 到 99 的數字,您需要[1-9]or [0-9][0-9](假設 C 語言環境 for[0-9][0123456789]並接受具有任意字節值的文件名)和 exclude 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實現在內部進行重新排序作為優化)

或者,您可以使用zsh其 glob 具有<x-y>十進制整數範圍運算符並支持遞歸 glob 和 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)' -- .

引用自:https://unix.stackexchange.com/questions/716566