Klasör karşılaştırması


10

Karşılaştırmak istediğim benzer alt klasör yapılarına sahip iki klasörüm var. Örneğin:

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

ve

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

Ben gösteren herkes alt klasörleri listelemek istiyorum Ahangi bir içinde alt klasör için önek olan Balt klasörler gelen ve listedeki Bsıra. Beklenen çıktı

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

İkincil bir gereklilik: Birden fazla eşleşme varsa B, bir hata / uyarı vermelidir.

Benim çözümüm :

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

Sorun:

$fKarşılık gelen alt klasörleri olmayan bu değerler Biçin dizi yapısı bana bir hata veriyor. Örneğin:

ls: 'child-4 *' dosyasına erişemiyor: Böyle bir dosya veya dizin yok

Soru

  • Bu hatalardan nasıl kurtulurum?
  • Kodumdaki hedeflere ulaşmak için daha iyi bir yol var mı ?

Şimdiden teşekkürler!


4
Neredeyse çalışan bir çözüm sağlamak için +1!
user5325

Bu, özel sorunuzun yanıtı diff -rq DIR1 DIR2değil, yalnızca dizin yapısını değil dosya içeriğini karşılaştırmak için de kullanabilirsiniz .
jrw32982 Monica

Yanıtlar:


10

Daha iyi bir yol

Ayrıştırmals ; yerine glob kullanın. Aslında zaten globları kullanıyorsunuz, sadece onları sarıyorsunuz ls, ki bu anlamsız. nullglobEşleşme olmadığında açık olmanız yeterlidir .

Ayrıca kaçınmak işleri cdkolaylaştırır.

#!/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

Çıktı:

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İkincil gereksinimi test etmek için ekledim . Bu test için dizin yapısını oluşturur:

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}

Bu arada, ShellCheck kabuk komut dosyalarında sorun bulmak için çok kullanışlıdır.


ShellCheck.net ilginç, her şeyi kendi sunucularına yükleyip yüklemediğini biliyor musunuz, yoksa hepsi yerel olarak mı yapılıyor? Sadece girilen bilgilerin gizliliğini merak ediyorum. [ shellcheckPaketin kurulması en güvenli olacaktır]
Xen2050

@ Xen2050 Sitede iken internetimi kapatmayı denedim ve yüklüyor gibi görünüyor. Onu tutmaz, ama emin değilim hayal ediyorum. Ve evet paket iyi; Bunu kullanan bir Atom eklentisi kullanıyorum.
wjandrea

Önerileriniz için teşekkürler. Ve ayrıca işaret ettiğiniz için tonlarca teşekkürler ShellCheck. Sadece hatalarınızı anlatmakla kalmayıp aynı zamanda önerilerde bulunduğunuz kısmı da çok sevdim! @ Xen2050, yükleme kısmı hakkında, sadece ağ shellcheckkullanarak yükledim aptve devre dışı bıraktım . İnternet olmadan çalışıyor gibi görünüyor .
Mike VDC

2

lsVarolmayan bir klasöre çağrı yapmak karşılaştığınız hata mesajını atar. Kolay yolu sadece bu ile komut satırı 5 değiştirerek bunu gözardı etmektir: new_dirs=(`ls -1d $f* 2> /dev/null`);.


Bunu test ettin mi? Stderr varsayılan olarak yok sayılıyor gibi görünüyor, ben t=(`echo ok; echo err 1>&2`)$ t (veya ${t[@]}) sadece Tamam içerir çalıştırdığınızda , err terminalde görülür ama yine de kaydedilmez. Yoksa testimde komik bir şey mi var?
Xen2050
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.