Memeriksa keberadaan beberapa direktori


8

Saya ingin memeriksa keberadaan beberapa direktori, katakanlah dir1,, dir2dan dir3, di direktori kerja.

Saya punya yang berikut ini

if [ -d "$PWD/dir1" ] && [ -d "$PWD/dir2" ] && [ -d "$PWD/dir3" ]; then
    echo True
else
    echo False
fi

Tapi saya curiga ada cara yang lebih elegan untuk melakukan ini. Jangan berasumsi bahwa ada pola dalam nama direktori.

Tujuannya adalah untuk memeriksa keberadaan beberapa direktori dan tidak adanya direktori lain.

Saya menggunakan Bash, tetapi kode portabel lebih disukai.


1
"Tujuannya adalah untuk memeriksa keberadaan beberapa direktori dan tidak adanya yang lain." Nah, contoh Anda memeriksa keberadaan semua direktori yang terdaftar. Bisakah Anda menguraikan bagian ini? Apakah semuanya terdaftar atau terdaftar? Apakah Anda memerlukan pemeriksaan bahwa nilai yang dikirimkan sebenarnya adalah direktori dan bukan jenis file lainnya?
Sergiy Kolodyazhnyy

1
Anda tidak perlu $PWD, omong-omong. [ -d "$PWD/dir1"]setara dengan [ -d "dir1" ].
terdon

Jawaban:


5

Jika Anda sudah mengharapkannya menjadi direktori dan hanya memeriksa apakah semuanya ada, Anda bisa menggunakan kode keluar dari lsutilitas untuk menentukan apakah satu atau lebih "kesalahan terjadi" :

ls "$PWD/dir1" "$PWD/dir2" "$PWD/dir3" >/dev/null 2>&1 && echo All there

Saya mengarahkan output dan stderr ke /dev/nulluntuk membuatnya menghilang, karena kita hanya peduli dengan kode keluar ls, bukan outputnya. Apa pun yang ditulis untuk /dev/nullmenghilang - tidak ditulis ke terminal Anda.


Bisakah Anda membantu saya memahami perintah ini? Saya tahu apa itu deskriptor file. Saya tahu 1stdout, 2stderr dan saya tahu apa itu redirect. Saya tidak mengerti pentingnya /dev/null, dan saya tidak tahu bagaimana menguraikan perintah.
Keanggunan

@Elegance Saya menambahkan sedikit penjelasan. Untuk jawaban lebih mendalam tentang / dev / null, lihat unix.stackexchange.com/questions/163352/… dan unix.stackexchange.com/questions/438130/…
Jeff Schaller

Masih mencoba mencari tahu bagaimana sintaks bekerja. Saya membaca bahwa &>filenamepengalihan stdout dan stderr ke filename. Jadi tidak bisakah perintah disederhanakan (setidaknya bagi saya itu lebih sederhana) ls "$PWD/dir1" "$PWD/dir2" "$PWD/dir2" &>/dev/null && echo All there?
Keanggunan

3
(1) Anda mungkin harus menggunakan -dopsi (a) jadi lshanya perlu membuat stat direktori, dan tidak membacanya, dan (b) sehingga perintah akan berhasil bahkan jika pengguna tidak memiliki akses baca ke direktori. (2) Saya tidak melihat alasan untuk menggunakan "$PWD/"kecuali untuk menjaga terhadap direktori yang namanya dimulai dengan -(dan, tentu saja, ada cara yang lebih baik untuk melakukan itu).
G-Man Mengatakan 'Reinstate Monica'

1
perintah ini bisa memakan waktu lebih lama untuk dijalankan daripada tes dalam pertanyaan aslinya. juga tidak memeriksa direktori.
Jasen

9

Saya akan mengulang:

result=True
for dir in \
        "$PWD/dir1" \
        "$PWD/dir2" \
        "$PWD/dir3" 
do
    if ! [ -d "$dir" ]; then
        result=False
        break
    fi
done
echo "$result"

The breakmenyebabkan loop untuk sirkuit pendek, seperti rantai Anda&&


5

Sebuah loop mungkin lebih elegan:

arr=("$PWD/dir1" "$PWD/dir2" "$PWD/dir2")
for d in "${arr[@]}"; do
    if [ -d "$d"]; then
        echo True
    else
        echo False
    fi
done

Ini Bash. Yang lebih portabel adalah Sh. Di sana Anda dapat menggunakan array posisi:

set -- "$PWD/dir1" "$PWD/dir2" "$PWD/dir2"

Kemudian untuk mengulanginya gunakan "$@".


5

Kenapa tidak adil:

if [ -d "dir1" -a -d "dir2" -a -d "dir3" ]; then
    echo True
else
    echo False
fi

Pada dasarnya inilah yang dimulai OP,But I suspect there is a more elegant way of doing this
Jeff Schaller

5
POSIX juga tidak menganjurkan penggunaan -a: " -adan -obinary primary (...) operator telah dianggap usang": pubs.opengroup.org/onlinepubs/9699919799
Elegance

@ JeffSchaller Ini lebih singkat karena melakukan semuanya dalam satu panggilan untuk menguji.
David Conrad

2
itu sama sekali tidak sama, panggilan asli test(alias [) tiga kali ini memanggil sekali,
Jasen

1
pubs.opengroup.org/onlinepubs/9699919799/utilities/... adalah referensi yang lebih tepat untuk lokasi pernyataan POSIX.
G-Man Mengatakan 'Reinstate Monica'

4

Sesuai pertanyaan, dua fungsi shell portabel yang menguji keberadaan dan tidak adanya beberapa direktori:

# Returns success if all given arguments exists and are directories.
ck_dir_exists () {
    for dir do
        [ -d "$dir" ] || return 1
    done
}

# Returns success if none of the given arguments are existing directories.
ck_dir_notexists () {
    for dir do
        [ ! -d "$dir" ] || return 1
    done
}

Contoh:

$ mkdir dir1 dir2
$ ck_dir_exists dir1 dir2; echo $?
0
$ ck_dir_exists dir1 dir2 dir3; echo $?
1
$ ck_dir_notexists dir1 dir2 dir3; echo $?
1
$ ck_dir_notexists dir3 dir4; echo $?
0

1

Tujuannya adalah untuk memeriksa keberadaan beberapa direktori dan tidak  adanya direktori lain. [Penekanan ditambahkan]

Berdasarkan jawaban glenn jackman , kita dapat menguji tidak adanya nama lain seperti ini:

hasil = Benar
untuk dir dalam \
        "$ PWD / dir1" \
        "$ PWD / dir2" \
        "$ PWD / dir3" 
melakukan
    jika! [-d "$ dir"]; kemudian
        hasil = Salah
        istirahat
    fi
selesai
untuk dir dalam \
        "$ PWD / dir4" \
        "$ PWD / dir5" \
        "$ PWD / dir6" 
melakukan
    jika [-e "$ dir"]; lalu # Catatan: tidak “!”
        hasil = Salah
        istirahat
    fi
selesai 
echo "$ hasil"
Saya dulu [ -e "$dir" ]menguji apakah "$dir"ada; yaitu, jika dir5ada tetapi merupakan file, hasilnya adalah False. Jika Anda hanya ingin menguji apakah nama-nama dalam grup kedua adalah direktori, gunakan [ -d "$dir" ], seperti pada loop pertama.

Karena kita berbicara tentang memeriksa keberadaan hal-hal di direktori kerja saat ini, mungkin tidak perlu untuk menentukan $PWD/nama-nama; kerjakan saja

untuk dir dalam \
        "dir1" \
        "dir2" \
        "dir3" 
melakukan
      ︙

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.