文件夹比较

Mik*_*.C. 10 bash directory

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

A 
??? child-1
??? child-2
??? child-3
??? child-4
??? child-5
Run Code Online (Sandbox Code Playgroud)

B 
??? child-1-some-text
??? child-2-more-text
??? child-3-nothing
??? child-6-random-text
??? child-7-more-random-text
Run Code Online (Sandbox Code Playgroud)

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

A 
??? child-1
??? child-2
??? child-3
??? child-4
??? child-5
Run Code Online (Sandbox Code Playgroud)

次要要求:如果在 中有多个匹配项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
Run Code Online (Sandbox Code Playgroud)

问题:

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

ls: 无法访问 'child-4*': 没有那个文件或目录

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

提前致谢!

wja*_*rea 10

更好的方法

不要解析ls;使用 globs 代替。事实上,您已经在使用 globs,只是将它们包装在 中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
Run Code Online (Sandbox Code Playgroud)

输出:

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/
Run Code Online (Sandbox Code Playgroud)

我添加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}
Run Code Online (Sandbox Code Playgroud)

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