Сравнение папки

У меня есть две папки с подобными подструктурами папок, которые я хотел бы сравнить. Например:

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: не может получить доступ 'к ребенку 4*': Никакой такой файл или каталог

Вопрос

  • Как избавиться от этих ошибок?
  • Там лучший путь состоит в том, чтобы достигнуть цели (целей) затем та в моем коде?

Заранее спасибо!

10
задан 24 March 2019 в 06:54

2 ответа

Лучший путь

Не анализировать ls; используйте шарики вместо этого. На самом деле Вы уже используете шарики, просто перенеся их в 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 очень полезен для нахождения проблем в сценариях оболочки.

10
ответ дан 23 November 2019 в 04:30

Вызов ls на не существующих бросках папки сообщение об ошибке, что Вы встретились. Простой способ состоит в том, чтобы просто проигнорировать это путем замены строки 5 в сценарии с этим: new_dirs=(`ls -1d $f* 2> /dev/null`);.

2
ответ дан 23 November 2019 в 04:30

Другие вопросы по тегам:

Похожие вопросы: