我发现自己需要查找和识别无关文件(在 2T 驱动器上的大约 900K 文件中)。我想保留很多文件,并且我有这些已知好的文件的文件名模式。我想要的是找到那些不符合任何模式的文件。
如何找到与文件名模式列表不匹配的文件?
我可以运行find
以获取所有文件的列表,并且可以使用grep -v
存储在文件中的模式列表对结果进行使用。这是规范的方法,还是您有一种简洁的方法可以找到这些不合格的文件?
澄清 - 根据答案,这里有更多信息。我希望有很多模式(> 20,也许> 100),我想将它们存储在一个文件中,当然想要一种添加新模式的简单方法。我宁愿避免直接编辑一大堆查找参数(脆弱),但构建该列表可能会奏效。
War*_*ung 23
find(1)
足够强大,可以做你需要的。只需使用括号将所有符合条件的名称收集到表达式中,然后将其取反以显示不符合条件的文件名。例如,要显示所有文件没有命名*.txt
,*.bz2
或*.zip
:
$ find . \! \( -name \*.txt -o -name \*.bz2 -o -name \*.zip \)
Run Code Online (Sandbox Code Playgroud)
您可以使用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 . "$@"
Run Code Online (Sandbox Code Playgroud)
这需要当前目录中的一个文件,.fnpatterns
每行一个模式。要模仿上面的单行,它需要包含:
*.txt
*.bz2
*.zip
Run Code Online (Sandbox Code Playgroud)
请注意,shell 脚本会*
为您转义模式中的字符。
您可以将其任意复杂化。一些想法:
添加-type f
到find
命令中,使其仅显示普通文件,而不显示目录。
将模式文件名作为参数传入,而不是将其放在固定位置
将模式文件保留在原处,但添加-o -name .fnpatterns
到内置find
命令中,使其不会出现在输出中。(这也将避免shift
黑客“吃掉”-o
内置表达式中的铅的需要。)
find
通过-exec
或类似方式向命令添加操作。
在模式文件中允许空行或注释
既然你提到了 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;
}
, '.' )
Run Code Online (Sandbox Code Playgroud)
将此调用为
/path/to/my/script file_with_patterns
Run Code Online (Sandbox Code Playgroud)
将末尾的替换.
为您要行走的树顶。