编辑2:
让我说我有2个目录,其中一个包含:
/dir1/Test File Name.txt
/dir1/This is anotherfile.txt
/dir1/And-Another File.txt
目录2看起来像:
/dir2/test-File_Name.txt
/dir2/test file_Name.txt
/dir2/This Is another file.txt
/dir2/And another_file.txt
如何查找(或匹配)名称相似的文件,在本示例中,dir1中的文件1与dir2中的文件1和2匹配,依此类推
尝试以bash方式执行此操作。假设我有一个名为“ Test File 1.txt”的文件,我想查找任何名称类似的文件:
test-file 1.txt
test file 1.txt
Test-file-1.txt
test-file_1.zip
等等等
我可以忽略find ./files/ -maxdepth 1 -iname $FILE
的大小写,但不知道如何忽略所有其他字符。
我可以用bash做到这一点吗?
编辑:
对不起,我忘了提到我需要遍历所有文件,文件名并不总是相同的,我只是用一个例子。
因此它可以命名为“ Test File 1.txt”,也可以命名为完全不同的“ Something Else.txt”
所以我想使用一个完整的文件名作为基础来查找所有相似的命名文件,但是这个文件名可以不同,希望我能理解。
答案 0 :(得分:2)
如果您选择Perl
,请尝试以下操作:
perl -e '
@files1 = glob "dir1/*";
@files2 = glob "dir2/*";
foreach (@files2) {
$f2 = $_;
s#.*/##; # remove directory name
# s#\..*?$##; # remove extension (wrong)
s#\.[^.]*$##; # remove extension (corrected)
s#[\W_]#[\\W_]?#g; # replace non-alphanumric chars
$pat = $_ . "\\.\\w+\$";
# print $pat, "\n"; # uncomment to see the regex pattern
foreach $f1 (@files1) {
if ($f1 =~ m#/$pat#i) {
print "$f1 <=> $f2\n";
}
}
}'
输出:
dir1/And-Another File.txt <=> dir2/And another_file.txt
dir1/Test File Name.txt <=> dir2/test file_Name.txt
dir1/Test File Name.txt <=> dir2/test-File_Name.txt
dir1/This is anotherfile.txt <=> dir2/This Is another file.txt
[说明]
概念是根据文件名动态生成正则表达式模式 在一个目录中,然后将其与另一目录中的文件进行匹配。
anotherfile
和another file
匹配。i
选项,启用了不区分大小写的匹配。可能的问题是我们无法生成与匹配的模式
来自文件名another file
的{{1}}。换句话说,
匹配是单向的。可能的解决方法是完全忽略匹配中的非字母数字字符和下划线。根据单词和标点,可能会导致意外的过度匹配。我们将需要具体定义anotherfile
才能进一步。
[编辑]
为了将结果返回到bash变量,请尝试:
similarity
结果逐行存储在bash变量while read -r -d "" line; do
# do something with the bash variable "line"
echo "$line"
done < <(
perl -e '
@files1 = glob "dir1/*";
@files2 = glob "dir2/*";
foreach (@files2) {
$f2 = $_;
s#.*/##; # remove directory name
# s#\..*?$##; # remove extension (wrong)
s#\.[^.]*$##; # remove extension (corrected)
s#[\W_]#[\\W_]?#g; # replace non-alphanumric chars
$pat = $_ . "\\.\\w+\$";
# print $pat, "\n"; # uncomment to see the regex pattern
foreach $f1 (@files1) {
if ($f1 =~ m#/$pat#i) {
push(@result, "$f1 <=> $f2");
# if you want just the list of filenames, comment out the line above
# and uncomment the line below
#push(@result, $f1, $f2);
}
}
}
print join("\0", @result) . "\0";
')
中。
如果要调整输出格式,请修改line
行。
[编辑]
已修改,可用于以下文件名对:
这是更新的代码:
push(@result, ...)