给定一个包含多个子目录和文件的目录X
,我想列出X
该目录(直接或间接)包含与 regex 匹配的文件名的直接子目录的名称^rf.*\.img$
。
在 OS X 上如何实现这一点?
答案1
使用 GNU find
,您可以测试每个目录:
for i in "$dir"/*/
do
test -n "$(find "$i" -type f -regex '.*/test[^/]*' -print -quit)" \
&& echo "$i"
done
这将在每个目录中搜索文件开头test
,如果找到则打印该目录。
有几点需要注意:
- 我忽略以
.
;开头的子目录如果需要考虑它们,请查看 Bash FAQ 以了解如何在不捕获 和 的情况下包含.
它们..
。 - 当我们有比赛时,我们会
find
提前退出。-quit
这可以节省大型文件系统树的时间。 - 测试
-regex
与 所考虑的整个路径名进行匹配find
,因此如果我们只想与基本名称进行匹配,则在匹配时需要小心/
。我们可以在没有此限制的情况下匹配通配符模式(并且不需要 GNU find),使用-filename
. - 您可以使用
-iregex
代替来-regex
进行不区分大小写的匹配。 - 您可以使用选项选择正则表达式语法
-regextype
。
对于问题中的具体模式,我们可以使用通配符,所以它变成:
for i in "$dir"/*/
do
test -n "$(find "$i" -type f -name 'rf*.img' -print -quit)" && echo "$i"
done
答案2
与zsh
(假设您已经在X
):
typeset -U subdirs
subdirs=(*/**/rf*.img(.e_'REPLY=${REPLY%%/*}'_))
print -rl -- "${subdirs[@]}"
这里 */**/rf*.img
对所有子目录中的所有文件进行 glob rf*.img
,glob 限定符.
并e
仅选择常规文件,并分别仅将路径的第一个组件保存在最初定义为具有唯一元素的数组(因此没有重复项)的数组中。然后它打印数组的每个元素。
答案3
(cd X && find . -type d -maxdepth 1 | sed -e 's,^./,,' | grep -E '^rf.*\.img$' )
我使用了一个子 shell 来获取里面的名称X
;否则就需要考虑 中的路径find
。
如果您想要递归子目录,可以省略该-maxdepth 1
选项。但这意味着您必须调整正则表达式,例如,
(cd X && find . -type d | sed -e 's,^./,,' | grep -E '^(.*/)?rf.*\.img$' )
在这种情况下,sed 命令是多余的(但无害)。
答案4
使用perl
和 其grep
和glob
。
#!/usr/bin/env perl
use strict;
use warnings;
my @file_list = grep { /^rf.*\.img$/ } glob "*";
print join ( "\n", @file_list );
或者作为一句单行:
perl -e 'print join ( "\n", grep { /^rf.*\.img$/ } glob "*" )'
注意 -glob
执行 shell 样式的通配符扩展,因此您可以glob "*/*/name/*"
或类似的。如果您需要任意递归深度,您可能需要使用File::Find
:
#!/usr/bin/env perl
use strict;
use warnings;
use File::Find;
sub print_match {
#Default match is against $_ which is filename.
#can match $File::Find::name for full name.
#or $File::Find::dir
print if /^rf.*\.img$/;
}
find ( \&print_match, "/path/to/search" );
再次作为一句:
perl -MFile::Find -e 'find ( sub { print if /^rf.*\.img$/ }, "/my/path/to/search" );'