资料夹比较


10

我有两个文件夹具有相似的子文件夹结构,我想进行比较。例如:

A 
├── child-1
├── child-2
├── child-3
├── child-4
├── child-5

B 
├── child-1-some-text
├── child-2-more-text
├── child-3-nothing
├── child-6-random-text
├── child-7-more-random-text

我想列出其中所有子文件夹A的前缀的所有那些子文件夹,B并列出相应的子文件夹B。预期的输出是

child-1 -- child-1-some-text
child-2 -- child-2-more-text
child-3 -- child-3-nothing

次要要求:如果中有多个匹配项B,则应该给出错误/警告。

我的解决方案

cd A
for f in `ls -d */`; 
do
    cd B;
    new_dirs=(`ls -1d $f*`);
    cd -;
    if [ ${#new_dirs[@]} -eq 0 ]
    then
        ## DO_Nothing
        continue;
    elif  [ ${#new_dirs[@]} -gt 1 ]
    then
        echo "Multiple matches to $f";
        continue;
    else
        echo "Unique Match found to $f -- ${new_dirs[0]}";
        continue;
    fi;    
done

问题:

对于那些$f在中没有对应子文件夹的值B,数组构造给我一个错误。例如:

ls:无法访问“ child-4 *”:没有此类文件或目录

  • 如何摆脱这些错误?
  • 是否有我代码中更好的方法来实现目标?

提前致谢!


4
+1提供几乎可行的解决方案!
user5325

这不是您的特定问题的答案,但您不仅可以diff -rq DIR1 DIR2用来比较目录结构,还可以用来比较文件内容。
jrw32982支持莫妮卡

Answers:


10

更好的方法

不要解析ls ; 改用glob。实际上,您已经在使用glob,只是将它们包装在中ls,这是没有意义的。您只需要nullglob在没有匹配项时打开。

还避免cd简化事情。

#!/bin/bash

shopt -s nullglob

dir1=A
dir2=B

for dir in "$dir1"/*/; do
    basename="$(basename -- "$dir")"
    dirs_match=( "$dir2/$basename"*/ )
    case ${#dirs_match[@]} in
    0)
        ;;
    1)
        echo "Unique match for $dir: ${dirs_match[*]}"
        ;;
    *)
        echo "Multiple matches for $dir: ${dirs_match[*]}" >&2
        ;;
    esac
done

输出:

Unique match for A/child-1/: B/child-1-some-text/
Unique match for A/child-2/: B/child-2-more-text/
Multiple matches for A/child-3/: B/child-3-nothing/ B/child-3-something/

我添加B/child-3-something了测试次要条件。这将创建用于测试的目录结构:

mkdir -p A/child-{1..5} B/child-{1-some-text,2-more-text,3-nothing,3-something,6-random-text,7-more-random-text}

顺便说一句,ShellCheck对于在Shell脚本中查找问题非常有用。


ShellCheck.net很有趣,您知道它是否将所有内容都上传到自己的服务器上,还是全部在本地完成?只是想知道输入信息的隐私性。[安装shellcheck软件包是最安全的]
Xen2050

@ Xen2050刚尝试在网站上切换互联网时,它似乎已上传。我想它不会保留它,但不确定。是的,包装很好。我使用一个使用它的Atom插件
wjandrea

感谢您的建议。同时也感谢您的指正ShellCheck。我喜欢这个部分,它不仅可以告诉您您的错误,还可以提供建议!@ Xen2050,关于上传部分,我刚刚shellcheck使用来安装apt,然后禁用了网络。似乎没有互联网就可以正常工作。
Mike VDC

2

调用ls不存在的文件夹将引发您遇到的错误消息。一种简单的方法是通过使用以下代码替换脚本中的第5行来忽略它new_dirs=(`ls -1d $f* 2> /dev/null`);


你测试过了吗?缺省情况下,Stderr似乎会被忽略,当我运行t=(`echo ok; echo err 1>&2`)$ t(或${t[@]})仅包含ok时,会在终端中看到err,但无论如何都不会保存。还是我的考试有些有趣?
Xen2050
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.