我发现自己需要查找和识别无关文件(在 2T 驱动器上的大约 900K 个文件中)。有很多文件我想保留,并且我有这些已知好文件的文件名模式。我想要的是找到那些不符合任何模式的文件。
如何查找与文件名模式列表不匹配的文件?
我可以运行find
来获取所有文件的列表,并且可以grep -v
使用存储在文件中的模式列表来使用结果。这是规范的方法,还是您有一种简洁的方法来查找这些不合格的文件?
澄清 - 根据答案,这里有更多信息。我期望有大量模式(>20,也许>100),我想将它们存储在一个文件中,并且当然想要一种简单的方法来添加新模式。我宁愿避免直接编辑大量查找参数(脆弱),但构建该列表可能会起作用。
答案1
find(1)
功能强大,足以满足您的需求。只需使用括号将所有符合的名称收集到一个表达式中,然后将其取反即可显示不合格文件名。例如,显示所有文件不是命名为*.txt
, *.bz2
, 或*.zip
:
$ find . \! \( -name \*.txt -o -name \*.bz2 -o -name \*.zip \)
您可以使用GNU 和 BSD 来-not
代替。它不符合 POSIX 标准,但不需要转义来阻止 shell 解释它。\!
find
要根据文件中的模式构建表达式,只需编写 shell 脚本即可:
#!/bin/sh
set --
while IFS= read -r pattern
do
set -- "$@" -o "$pattern"
done < .fnpatterns
if [ $# -ne 0 ]; then
shift
set -- -not \( "$@" \)
fi
find . "$@"
这需要当前目录中的一个文件,.fnpatterns
每行调用一个模式。为了模仿上面的一行,它需要包含:
*.txt
*.bz2
*.zip
请注意,shell 脚本会*
为您转义模式中的字符。
您可以将其变得任意复杂。一些想法:
添加
-type f
到find
命令中,使其仅显示普通文件,而不显示目录。将模式文件名作为参数传递,而不是期望它位于固定位置
将模式文件保留在原来的位置,但添加
-o -name .fnpatterns
到构建find
命令中,这样它就不会显示在输出中。 (这也可以避免黑客shift
“吃掉”-o
构建表达式中的铅。)find
通过或类似方式向命令添加操作-exec
。模式文件中允许空行或注释
答案2
既然你提到了 Perl...
#!/usr/bin/perl
use strict;
use warnings;
use File::Find qw{find};
my %patterns;
while (<>) {
chomp;
$patterns{$_}++;
}
die "No pattern supplied\n" unless keys %patterns;
find(
sub{
my $matches_a_pattern=0;
for my $pattern (keys %patterns){
my $glob_pattern = $pattern;
for($glob_pattern){
s/\./\\./g;
s/\*/.*/g;
s/\?/./g;
}
$matches_a_pattern++ if ( /\Q$pattern\E/ or /$glob_pattern/);
}
print "$File::Find::name\n" unless $matches_a_pattern;
}
, '.' )
将此调用为
/path/to/my/script file_with_patterns
将末尾的 替换.
为您要行走的树顶。