是否可以找到忽略大小写,破折号,空格或其他字符的类似命名文件?

时间:2019-02-11 19:44:34

标签: bash

编辑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”

所以我想使用一个完整的文件名作为基础来查找所有相似的命名文件,但是这个文件名可以不同,希望我能理解。

1 个答案:

答案 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

[说明]

概念是根据文件名动态生成正则表达式模式 在一个目录中,然后将其与另一目录中的文件进行匹配。

  • 文件扩展名将替换为与其匹配的模式。
  • 非字母数字字符和下划线替换为模式 与他们匹配,包括缺少角色的情况,以便 anotherfileanother 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行。

[编辑]

已修改,可用于以下文件名对:

  • “示例文件名.txt” <=>“示例文件名(100).txt”
  • “ Sample.Filename.txt” <=>“ Sample Filename.txt”

这是更新的代码:

push(@result, ...)