Perbandingan folder

10

Saya memiliki dua folder dengan struktur subfolder yang serupa, yang ingin saya bandingkan. Sebagai contoh:

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

dan

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

Saya ingin membuat daftar semua subfolder dari Ayang merupakan awalan untuk subfolder Bdan daftar subfolder yang sesuai dari Bjuga. Output yang diharapkan adalah

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

Persyaratan sekunder: Jika banyak yang cocok B, maka harus memberikan kesalahan / peringatan.

Solusi saya :

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

Masalah:

Untuk nilai-nilai dari $f, yang tidak memiliki subfolder yang sesuai B, konstruksi array memberi saya kesalahan. misalnya:

ls: tidak dapat mengakses 'child-4 *': Tidak ada file atau direktori tersebut

Pertanyaan

  • Bagaimana cara menghilangkan kesalahan ini?
  • Apakah ada cara yang lebih baik untuk mencapai tujuan daripada yang ada di kode saya?

Terima kasih sebelumnya!

Mike VDC
sumber
4
+1 untuk memberikan solusi yang hampir berfungsi!
user5325
Ini bukan jawaban untuk pertanyaan spesifik Anda, tetapi Anda dapat menggunakan diff -rq DIR1 DIR2untuk membandingkan tidak hanya struktur direktori, tetapi isi file.
jrw32982 mendukung Monica

Jawaban:

10

Cara yang lebih baik

Jangan diurails ; gunakan gumpalan sebagai gantinya. Bahkan Anda sudah menggunakan gumpalan, hanya membungkusnya ls, yang tidak ada gunanya. Anda hanya perlu nullglobdihidupkan ketika tidak ada kecocokan.

Juga menghindari cdhal-hal yang disederhanakan.

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

Keluaran:

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/

Saya menambahkan B/child-3-somethinguntuk menguji persyaratan sekunder. Ini menciptakan struktur direktori untuk pengujian:

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}

Omong-omong, ShellCheck sangat berguna untuk menemukan masalah dalam skrip shell.

wjandrea
sumber
ShellCheck.net menarik, tahukah Anda jika semuanya diunggah ke server sendiri, atau apakah semuanya dilakukan secara lokal? Hanya ingin tahu tentang privasi info yang dimasukkan. [Menginstal shellcheckpaket akan menjadi yang paling aman]
Xen2050
@ Xen2050 Baru saja mencoba mematikan internet saya saat berada di situs, dan sepertinya mengunggah. Saya akan membayangkan itu tidak menyimpannya, tetapi tidak yakin. Dan ya paketnya bagus; Saya menggunakan plugin Atom yang menggunakannya.
wjandrea
Terima kasih atas sarannya. Dan juga banyak terima kasih atas pengarahannya ShellCheck. Saya menyukai bagian yang tidak hanya memberi tahu Anda kesalahan Anda, tetapi juga memberikan saran! @ Xen2050, tentang bagian pengunggahan, saya baru saja menginstal shellcheckmenggunakan aptdan kemudian menonaktifkan jaringan. Tampaknya berfungsi tanpa internet .
Mike VDC
2

Memanggil lsfolder yang tidak ada melempar pesan kesalahan yang Anda temui. Cara mudah adalah dengan hanya mengabaikan ini dengan mengganti baris 5 di naskah Anda dengan ini: new_dirs=(`ls -1d $f* 2> /dev/null`);.

cauon
sumber
Sudahkah Anda menguji ini? Stderr tampaknya diabaikan secara default, ketika saya menjalankan t=(`echo ok; echo err 1>&2`)$ t (atau ${t[@]}) hanya berisi ok, err terlihat di terminal tetapi tidak disimpan. Atau adakah yang lucu dengan ujian saya?
Xen2050