我有两个文件夹具有相似的子文件夹结构,我想进行比较。例如:
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*”:没有该文件或目录
问题
- 如何摆脱这些错误?
- 有没有更好的实现目标的方法然后是我的代码中的方法?
提前致谢!
答案1
更好的方法
不要解析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
输出:
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}
顺便一提,壳牌检测对于查找 shell 脚本中的问题非常有用。
答案2
调用ls
不存在的文件夹会抛出您遇到的错误消息。简单的方法是将脚本中的第 5 行替换为以下内容来忽略此错误:new_dirs=(`ls -1d $f* 2> /dev/null`);
。