我有这样的文件:
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
?
*
[...]
\
-regex
find
要使用基本 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
实现在内部进行重新排序作为优化)
或者您可以使用zsh
who 的 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)' -- .