列出没有匹配对的文件(递归)

时间:2017-06-08 15:51:11

标签: bash

我在多个目录中有一组文件。他们中的大多数都有一个相关的对,具有不同的扩展名和相同的基本名称。相关文件始终位于同一目录中。我需要在包含所有子目录的目录中仅列出没有对的文件(和路径)。我怎么能用bash做到这一点?

[ "foo", "foo\",bar", "bar" ]

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:2)

您可以使用find和pipe to perl对数据进行排序

find . -type f -print0 |\
perl -0 -l012 -ne 'if(/.*\/(.*)\./){$x{$1}++;$y{$1}=$_}
}{for(keys %x){print $y{$_} if $x{$_}==1}'

这为每个匹配的哈希和增量添加了没有后缀的名称,同时将整行添加到具有相同键的另一个哈希。

最后,它只检查哪一个匹配并打印。

由于文件名以空分隔,因此它应该适用于所有文件名。

答案 1 :(得分:1)

您可以列出目录下的所有文件,然后计算在相同路径名称(不包括扩展名)的同一树目录中可以找到的全名匹配项数。

如果您的文件与较少或一个名称匹配,则表示它没有“随播”文件:

for f in $(find -type f); do 
    c=$(find -wholename "$(echo $f | rev | cut --complement -d . -f 1 | rev).*" | wc -l);  
    if [ "$c" -le "1" ]; then echo $f; fi; 
done 

修改

如果模式组合在不同的行中执行,则可能更具可读性:

for f in $(find -type f); do 
    compPattern="$(echo $f | rev | cut --complement -d . -f 1 | rev).*" 
    c=$(find -wholename "$compPattern" | wc -l);
    if [ "$c" -le "1" ]; then echo $f; fi; 
done

修改(2)

为避免解析find的输出,您可以使用read:

find -type f | while read f; do 
    if [ $(find -wholename "$(echo $f | rev | cut --complement -d . -f 1 | rev).*" | wc -l) -le "1" ]; then echo $f; fi; 
done 

修改(3)

要处理特殊字符,空格等,您可以使用以下内容。

while IFS= read -r -d '' f ; do
    c=$(find -wholename "$(echo $f | rev | cut --complement -d . -f 1 | rev).*" | wc -l);
    if [ "$c" -le "1" ]; then echo $f; fi;
done < <(find -type f -print0)