Dari skrip shell, bagaimana cara memeriksa apakah direktori berisi file?
Sesuatu yang mirip dengan ini
if [ -e /some/dir/* ]; then echo "huzzah"; fi;
tetapi yang berfungsi jika direktori berisi satu atau beberapa file (yang di atas hanya berfungsi dengan tepat 0 atau 1 file).
Jawaban:
Solusi yang digunakan sejauh ini
ls
. Inilah solusi semua bash:sumber
shopt -q nullglob || resetnullglob=1; shopt -s nullglob; shopt -q dotglob || resetdotglob=1; shopt -s dotglob; files=(/some/dir/*); [ "$files" ] && echo "wowzers"; [ "$resetdotglob" ] && shopt -u dotglob; [ "$resetnullglob" ] && shopt -u nullglob;
files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*)
files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*)
maka pernyataan if harus berubah menjadiif [ ${#files} -gt 0 ];
atau mungkin Anda lupa () di sekitar perintah sub-shell?files=($(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*))
Tiga trik terbaik
shopt -s nullglob dotglob; f=your/dir/*; ((${#f}))
Trik ini 100%
bash
dan memanggil (memunculkan) sub-shell. Ide ini dari Bruno De Fraine dan ditingkatkan dengan komentar teambob .Catatan: tidak ada perbedaan antara direktori kosong dan yang tidak ada (dan bahkan jika jalur yang diberikan adalah file).
Ada alternatif serupa dan detail lebih lanjut (dan lebih banyak contoh) di FAQ 'resmi' untuk saluran IRC #bash :
[ -n "$(ls -A your/dir)" ]
Trik ini terinspirasi dari artikel nixCraft yang diposting pada tahun 2007. Tambahkan
2>/dev/null
untuk menekan kesalahan keluaran"No such file or directory"
.Lihat juga jawaban Andrew Taylor (2008) dan jawaban gr8can8dian (2011).
atau versi bashism satu baris:
Catatan:
ls
kembali$?=2
jika direktori tidak ada. Tetapi tidak ada perbedaan antara file dan direktori kosong.[ -n "$(find your/dir -prune -empty)" ]
Trik terakhir ini terinspirasi dari jawaban gravstar ini di mana
-maxdepth 0
digantikan oleh-prune
dan diperbaiki oleh phils komentar 's.variasi menggunakan
-type d
:Penjelasan:
find -prune
miripfind -maxdepth 0
dengan menggunakan lebih sedikit karakterfind -empty
mencetak direktori dan file kosongfind -type d
mencetak direktori sajaCatatan: Anda juga dapat mengganti
[ -n "$(find your/dir -prune -empty)" ]
hanya dengan versi singkat di bawah ini:Kode terakhir ini berfungsi pada sebagian besar kasus, tetapi ketahuilah bahwa jalur berbahaya dapat mengekspresikan perintah ...
sumber
[ -n "$(find "your/dir" -prune -empty)" ]
, untuk menghindari pengulangan jalur direktori.if [ ``ls -A your/dir`` ]
skrip, saya sampai pada kesimpulan bahwa itu berfungsi dengan baik untuk direktori dengan 0, 1 atau 2 subdirektori, tetapi gagal untuk direktori dengan lebih dari 2 subdirektori.line 17: [: 20150424-002813: unary operator expected
di mana20150424-002813
salah satu nama direktorinya. Cangkang bekas itu/bin/bash/
. Saya akhirnya mengubahnya menjadils "$destination" | tail -1
if [ ``ls -A my/dir`` ]
keluar karena kesalahanbash: [: -A: binary operator expected
. Diuji pada bash versi 4.1.2 dan 4.2.53.-n
varian ada di tajuk utama tetapi kemudian tidak di paragraf di bawah). Jadi, ya, tidak apa-apa.ls: cannot access '/path': No such file or directory
. Adakah cara agar saya bisa menyembunyikan pesan ini? Saya ingin gagal diam-diam di sana.Bagaimana dengan yang berikut ini:
Dengan cara ini tidak perlu membuat daftar lengkap dari isi direktori. Itu
read
adalah untuk membuang keluaran dan membuat ekspresi mengevaluasi menjadi benar hanya ketika sesuatu dibaca (yaitu/some/dir/
ditemukan kosong olehfind
).sumber
find /some/dir/ -maxdepth 0 -empty -exec echo "huzzah" \;
ls
output dan tidak bergantung pada fitur shell non-default.-maxdepth
dan-empty
pendahuluan.Mencoba:
sumber
/bin/ls <some_dir>/* 2> /dev/null
if [! -z "$ tmp"]; lalu gema Sesuatu yang ada di sana fils /some/dir/*
]; lalu echo "huzzah"; fi-n
alih-alih! -z
(keduanya setara, tetapi mengapa tidak menggunakan formulir yang lebih pendek jika sudah ada).BigGray% if [ ! -z
ls / some / dir / * `]; lalu echo "huzzah"; fi zsh: tidak ada kecocokan yang ditemukan: / some / dir / * `ls...
di bashsumber
Jaga direktori dengan banyak file! Mungkin perlu beberapa saat untuk mengevaluasi
ls
perintah.IMO solusi terbaik adalah yang menggunakan
sumber
sumber
Bisakah Anda membandingkan hasilnya?
sumber
Beberapa catatan implementasi:
for
Loop menghindari panggilan ke eksternalls
proses. Itu masih membaca semua entri direktori sekali. Ini hanya dapat dioptimalkan dengan menulis program C yang menggunakan readdir () secara eksplisit.test -e
dalam loop menangkap kasus direktori kosong, dalam hal ini variabel_ief
akan diberi nilai "somedir / *". Hanya jika file itu ada, fungsi akan mengembalikan "tidak kosong"test
implementasi tidak mendukung-e
bendera.sumber
dotglob
tidak disetel -shopt -s dotglob
Ini memberi tahu saya jika direktori kosong atau jika tidak, jumlah file di dalamnya.
sumber
ls
.Ini mungkin respons yang sangat terlambat, tetapi ini adalah solusi yang berhasil. Baris ini hanya mengenali keberadaan file! Ini tidak akan memberi Anda positif palsu jika direktori ada.
sumber
Asumsikan Anda tidak memiliki file bernama
*
ke/any/dir/you/check
, itu harus bekerjabash
dash
posh
busybox sh
danzsh
tetapi (untuk zsh) membutuhkanunsetopt nomatch
.Performa harus sebanding dengan
ls
yang menggunakan*
(glob), saya kira akan lambat pada direktori dengan banyak node (saya/usr/bin
dengan 3000+ file tidak terlalu lambat), akan menggunakan setidaknya memori yang cukup untuk mengalokasikan semua dirs / nama file (dan banyak lagi) karena semuanya diteruskan (diselesaikan) ke fungsi sebagai argumen, beberapa shell mungkin memiliki batasan jumlah argumen dan / atau panjang argumen.Cara portabel cepat O (1) tanpa sumber daya untuk memeriksa apakah direktori kosong akan menyenangkan untuk dimiliki.
memperbarui
Versi di atas tidak memperhitungkan tersembunyi file / dirs, dalam kasus beberapa tes yang lebih diperlukan, seperti
is_empty
dari sh Rich (POSIX shell) trik :Tapi, sebaliknya, saya sedang memikirkan sesuatu seperti ini:
Beberapa kekhawatiran tentang perbedaan garis miring tertinggal dari argumen dan keluaran pencarian ketika dir kosong, dan mengikuti baris baru (tetapi ini harus mudah ditangani), sayangnya di
busybox
sh
acara saya apa yang mungkin merupakan bug padafind -> dd
pipa dengan keluaran terpotong secara acak ( jika saya menggunakancat
output selalu sama, sepertinyadd
dengan argumencount
).sumber
is_empty(){ [ ! -d "${1}" ] && return 2;set -- "${1}" "${1}"/* "${1}"/.[!.]* "${1}"/..?*;[ "${*}" = "${1} ${1}/* ${1}/.[!.]* ${1}/..?*" ]; };
ZSH
Saya tahu pertanyaan itu ditandai untuk pesta; tapi, hanya untuk referensi, untuk pengguna zsh :
Uji direktori yang tidak kosong
Untuk memeriksa apakah
foo
tidak kosong:dimana, jika
foo
tidak kosong, kode difor
blok tersebut akan dieksekusi.Uji direktori kosong
Untuk memeriksa apakah
foo
kosong:dimana, jika
foo
kosong, kode difor
blok tersebut akan dieksekusi.Catatan
Kami tidak perlu mengutip direktori di
foo
atas, tetapi kami dapat melakukannya jika kami perlu:Kami juga dapat menguji lebih dari satu objek, meskipun itu bukan direktori:
Apa pun yang bukan direktori akan diabaikan begitu saja.
Ekstra
Karena kita melakukan globbing, kita dapat menggunakan glob (atau ekspansi brace) apa pun:
Kami juga dapat memeriksa objek yang ditempatkan dalam sebuah array. Dengan direktori seperti di atas, misalnya:
Jadi, kita bisa menguji objek yang mungkin sudah disetel dalam parameter array.
Perhatikan bahwa kode di
for
blok tersebut, jelas, dijalankan pada setiap direktori secara bergantian. Jika ini tidak diinginkan maka Anda cukup mengisi parameter array dan kemudian mengoperasikan parameter itu:Penjelasan
Untuk pengguna zsh ada
(F)
pengualifikasi glob (lihatman zshexpn
), yang cocok dengan direktori "full" (tidak kosong):Qualifier
(F)
mencantumkan objek yang cocok: adalah direktori DAN tidak kosong. Jadi,(^F)
kecocokan: bukan direktori ATAU kosong. Jadi,(^F)
sendiri juga akan mencantumkan file biasa, misalnya. Jadi, seperti yang dijelaskan dizshexp
halaman manual, kita juga membutuhkan(/)
pengualifikasi glob, yang hanya mencantumkan direktori:Jadi, untuk memeriksa apakah direktori tertentu kosong, Anda dapat menjalankan:
dan hanya untuk memastikan bahwa direktori yang tidak kosong tidak akan ditangkap:
Ups! Karena
Y
tidak kosong, zsh tidak menemukan kecocokan untuk(/^F)
("direktori yang kosong") dan dengan demikian mengeluarkan pesan kesalahan yang mengatakan bahwa tidak ada kecocokan untuk glob yang ditemukan. Oleh karena itu, kami perlu menyembunyikan kemungkinan pesan kesalahan ini dengan(N)
pengualifikasi glob:Jadi, untuk direktori kosong kita membutuhkan qualifier
(N/^F)
, yang bisa dibaca sebagai: "jangan peringatkan saya tentang kegagalan, direktori yang tidak penuh".Demikian pula, untuk direktori yang tidak kosong kita memerlukan qualifier
(NF)
, yang juga bisa kita baca sebagai: "jangan peringatkan saya tentang kegagalan, direktori lengkap".sumber
Saya terkejut panduan wooledge tentang direktori kosong belum disebutkan. Panduan ini, dan semua wooledge benar-benar, harus dibaca untuk pertanyaan tipe shell.
Catatan dari halaman itu:
sumber
Variasi kecil dari jawaban Bruno :
Ini bekerja untuk saya
sumber
Mengambil petunjuk (atau beberapa) dari jawaban olibre, saya suka fungsi Bash:
Karena sementara itu membuat satu subkulit, itu sedekat mungkin dengan solusi O (1) seperti yang saya bayangkan dan memberinya nama membuatnya dapat dibaca. Saya kemudian bisa menulis
Adapun O (1) ada kasus pencilan: jika direktori besar memiliki semua atau semua kecuali entri terakhir dihapus, "temukan" mungkin harus membaca semuanya untuk menentukan apakah itu kosong. Saya percaya bahwa kinerja yang diharapkan adalah O (1) tetapi kasus terburuk adalah linier dalam ukuran direktori. Saya belum mengukur ini.
sumber
Sejauh ini saya belum melihat jawaban yang menggunakan grep yang menurut saya akan memberikan jawaban yang lebih sederhana (dengan tidak terlalu banyak simbol aneh!). Berikut adalah cara saya memeriksa apakah ada file yang ada di direktori menggunakan bourne shell:
ini mengembalikan jumlah file dalam direktori:
Anda dapat mengisi jalur direktori tempat direktori ditulis. Paruh pertama pipa memastikan bahwa karakter pertama dari keluaran adalah "-" untuk setiap file. egrep kemudian menghitung jumlah baris yang dimulai dengan simbol itu menggunakan ekspresi reguler. sekarang yang harus Anda lakukan adalah menyimpan nomor yang Anda peroleh dan membandingkannya menggunakan kutipan latar seperti:
x adalah variabel pilihan Anda.
sumber
Mencampur hal-hal pangkas dan jawaban terakhir, saya harus
yang berfungsi untuk jalur dengan spasi juga
sumber
Jawaban sederhana dengan bash :
sumber
Saya akan memilih
find
:Ini memeriksa output dari hanya mencari file di direktori, tanpa melalui subdirektori. Kemudian ia memeriksa output menggunakan
-z
opsi yang diambil dariman test
:Lihat beberapa hasil:
Dir kosong:
Hanya dirs di dalamnya:
File di direktori:
File di subdirektori:
sumber
Dengan beberapa solusi, saya dapat menemukan cara sederhana untuk mengetahui apakah ada file dalam sebuah direktori. Ini dapat diperluas dengan perintah grep untuk memeriksa secara spesifik file .xml atau .txt, dll. Contoh:
ls /some/dir | grep xml | wc -l | grep -w "0"
sumber
sumber
nullglob
, karenals
perintah akan berhasil.untuk menguji direktori target tertentu
sumber
Coba dengan command find. Tentukan direktori hardcode atau sebagai argumen. Kemudian mulai temukan untuk mencari semua file di dalam direktori. Periksa apakah return of find null. Gema data temukan
sumber
Saya tidak suka
ls - A
solusi yang diposting. Kemungkinan besar Anda ingin menguji apakah direktori tersebut kosong karena Anda tidak ingin menghapusnya. Berikut ini yang melakukannya. Namun, jika Anda hanya ingin mencatat file kosong, pasti menghapus dan membuatnya lebih cepat kemudian mendaftar file yang mungkin tidak terbatas?Ini harus bekerja ...
sumber
${target}/..
.Bekerja dengan baik untuk saya ini (saat dir ada):
Dengan cek lengkap:
sumber