it-swarm-id.com

Memeriksa dari skrip Shell jika direktori berisi file

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).

95
ionn

Solusi sejauh ini menggunakan ls. Inilah solusi semua bash:

#!/bin/bash
shopt -s nullglob dotglob     # To include hidden files
files=(/some/dir/*)
if [ ${#files[@]} -gt 0 ]; then echo "huzzah"; fi
61
Bruno De Fraine

Tiga trik terbaik


shopt -s nullglob dotglob; f=your/dir/*; ((${#f}))

Trik ini 100% bash dan memanggil (menumbuhkan) sub-Shell. Idenya adalah dari Bruno De Fraine dan ditingkatkan oleh komentar teambob

files=$(shopt -s nullglob dotglob; echo your/dir/*)
if (( ${#files} ))
then
  echo "contains files"
else 
  echo "empty (or does not exist or is a file)"
fi

Catatan: tidak ada perbedaan antara direktori kosong dan yang tidak ada (dan bahkan ketika path yang disediakan adalah file).

Ada alternatif serupa dan lebih banyak detail (dan lebih banyak contoh) pada saluran 'resmi' FAQ untuk saluran #bash IRC :

if (shopt -s nullglob dotglob; f=(*); ((${#f[@]})))
then
  echo "contains files"
else 
  echo "empty (or does not exist, or is a file)"
fi

[ -n "$(ls -A your/dir)" ]

Trik ini terinspirasi dari artikel nixCraft yang diposting pada tahun 2007. Tambahkan 2>/dev/null untuk menekan kesalahan output "No such file or directory".
Lihat juga jawaban Andrew Taylor (2008) dan gr8can8dian jawaban (2011).

if [ -n "$(ls -A your/dir 2>/dev/null)" ]
then
  echo "contains files (or is a file)"
else
  echo "empty (or does not exist)"
fi

atau versi bashism satu baris:

[[ $(ls -A your/dir) ]] && echo "contains files" || echo "empty"

Catatan:ls mengembalikan $?=2 ketika 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 di mana -maxdepth 0 digantikan oleh -Prune dan ditingkatkan dengan komentar phils .

if [ -n "$(find your/dir -Prune -empty 2>/dev/null)" ]
then
  echo "empty (directory or file)"
else
  echo "contains files (or does not exist)"
fi

variasi menggunakan -type d:

if [ -n "$(find your/dir -Prune -empty -type d 2>/dev/null)" ]
then
  echo "empty directory"
else
  echo "contains files (or does not exist or is not a directory)"
fi

Penjelasan: 

  • find -Prune mirip dengan find -maxdepth 0 menggunakan lebih sedikit karakter
  • find -empty mencetak direktori dan file yang kosong
  • find -type d hanya mencetak direktori

Catatan: Anda juga bisa mengganti [ -n "$(find your/dir -Prune -empty)" ] hanya dengan versi singkat di bawah ini:

if [ `find your/dir -Prune -empty 2>/dev/null` ]
then
  echo "empty (directory or file)"
else
  echo "contains files (or does not exist)"
fi

Kode terakhir ini berfungsi sebagian besar kasus tetapi perlu diketahui bahwa jalur jahat dapat mengekspresikan perintah ...

114
olibre

Bagaimana dengan yang berikut ini:

if find /some/dir/ -maxdepth 0 -empty | read v; then echo "Empty dir"; fi

Dengan cara ini tidak perlu membuat daftar lengkap dari isi direktori. read adalah untuk membuang output dan membuat ekspresi hanya bernilai true ketika sesuatu dibaca (mis. /some/dir/ ditemukan kosong oleh find).

47
mweerden

Mencoba:

if [ ! -z `ls /some/dir/*` ]; then echo "huzzah"; fi
19
Greg Hewgill
# Works on hidden files, directories and regular files
### isEmpty()
# This function takes one parameter:
# $1 is the directory to check
# Echoes "huzzah" if the directory has files
function isEmpty(){
  if [ "$(ls -A $1)" ]; then
    echo "huzzah"
  else 
    echo "has no files"
  fi
}
14
gr8can8dian

Jaga direktori dengan banyak file! Diperlukan waktu untuk mengevaluasi perintah ls.

IMO solusi terbaik adalah yang digunakan 

find /some/dir/ -maxdepth 0 -empty
12
Gravstar
DIR="/some/dir"
if [ "$(ls -A $DIR)" ]; then
     echo 'There is something alive in here'
fi
9
Andrew Taylor

Bisakah Anda membandingkan output ini?

 ls -A /some/dir | wc -l
5
DGM
 # Memeriksa apakah direktori berisi file yang tidak disembunyikan .
 # 
 # Penggunaan: jika isempty "$ HOME"; lalu gema "Selamat datang di rumah"; fi 
 # 
 isempty () {
 untuk _ief dalam $ 1/*; melakukan
 jika [-e "$ _ief"]; kemudian
 return 1 
 fi 
 selesai 
 return 0 
} 

Beberapa catatan implementasi:

  • Loop for menghindari panggilan ke proses ls eksternal. Itu masih membaca semua entri direktori sekali. Ini hanya dapat dioptimalkan dengan menulis program C yang menggunakan readdir () secara eksplisit.
  • test -e di dalam loop menangkap case dari direktori kosong, di mana variabel _ief akan diberi nilai "somedir/*". Hanya jika file itu ada maka fungsi akan mengembalikan "nonempty"
  • Fungsi ini akan bekerja di semua implementasi POSIX. Namun ketahuilah bahwa Solaris/bin/sh tidak termasuk dalam kategori itu. Implementasinya test tidak mendukung flag -e.
4
Roland Illig

Ini memberitahu saya jika direktori kosong atau jika tidak, jumlah file di dalamnya.

directory="/some/dir"
number_of_files=$(ls -A $directory | wc -l)

if [ "$number_of_files" == "0" ]; then
    echo "directory $directory is empty"
else
    echo "directory $directory contains $number_of_files files"
fi
3
Daishi

Ini mungkin respons yang sangat terlambat, tetapi di sini ada solusi yang berfungsi. Baris ini hanya mengenali keberadaan file! Itu tidak akan memberi Anda false positive jika direktori ada.

if find /path/to/check/* -maxdepth 0 -type f | read
  then echo "Files Exist"
fi
2
bitstreamer
dir_is_empty() {
   [ "${1##*/}" = "*" ]
}

if dir_is_empty /some/dir/* ; then
   echo "huzzah"
fi

Asumsikan Anda tidak memiliki file bernama * ke /any/dir/you/check, itu harus berfungsi pada bashdashposhbusybox sh dan zsh tetapi (untuk zsh) memerlukan unsetopt nomatch.

Pertunjukan harus sebanding dengan ls yang menggunakan * (glob), saya kira akan lambat pada direktori dengan banyak node (/usr/bin saya dengan 3000+ file tidak terlalu lambat), akan menggunakan setidaknya memori yang cukup untuk mengalokasikan semua dir/filenames ( dan lebih banyak lagi) karena semuanya diteruskan (diselesaikan) ke fungsi sebagai argumen, beberapa Shell mungkin memiliki batasan jumlah argumen dan/atau panjang argumen.

Sebuah fast portable O(1) nol sumber daya cara untuk memeriksa apakah direktori kosong akan menyenangkan untuk dimiliki.

perbarui

Versi di atas tidak memperhitungkan file/dirs yang tersembunyi, jika diperlukan beberapa tes lagi, seperti is_empty dari trik Kaya (POSIX Shell) }:

is_empty () (
cd "$1"
set -- .[!.]* ; test -f "$1" && return 1
set -- ..?* ; test -f "$1" && return 1
set -- * ; test -f "$1" && return 1
return 0 )

Tetapi, sebaliknya, saya berpikir tentang sesuatu seperti ini:

dir_is_empty() {
    [ "$(find "$1" -name "?*" | dd bs=$((${#1}+3)) count=1 2>/dev/null)" = "$1" ]
}

Beberapa kekhawatiran tentang trailing memangkas perbedaan dari argumen dan output find ketika dir kosong, dan tertinggal baris baru (tapi ini harus mudah ditangani), sayangnya pada busyboxsh saya menunjukkan apa yang mungkin merupakan bug pada pipa find -> dd dengan output terpotong secara acak (jika saya menggunakan cat hasilnya selalu sama, tampaknya dd dengan argumen count).

1
Alex

ZSH

Saya tahu pertanyaan itu ditandai untuk bash; tetapi, hanya untuk referensi, untuk zsh pengguna:

Tes untuk direktori yang tidak kosong

Untuk memeriksa apakah foo tidak kosong:

$ for i in foo(NF) ; do ... ; done

di mana, jika foo adalah non-kosong, kode di blok for akan dieksekusi.

Tes untuk direktori kosong

Untuk memeriksa apakah foo kosong:

$ for i in foo(N/^F) ; do ... ; done

di mana, jika foo kosong, kode di blok for akan dieksekusi.

Catatan

Kami tidak perlu mengutip direktori foo di atas, tetapi kami dapat melakukannya jika perlu:

$ for i in 'some directory!'(NF) ; do ... ; done

Kami juga dapat menguji lebih dari satu objek, meskipun itu bukan direktori:

$ mkdir X     # empty directory
$ touch f     # regular file
$ for i in X(N/^F) f(N/^F) ; do echo $i ; done  # echo empty directories
X

Apa pun yang bukan direktori hanya akan diabaikan.

Ekstra

Karena kita melakukan globbing, kita dapat menggunakan glob (atau penjepit ekspansi):

$ mkdir X X1 X2 Y Y1 Y2 Z
$ touch Xf                    # create regular file
$ touch X1/f                  # directory X1 is not empty
$ touch Y1/.f                 # directory Y1 is not empty
$ ls -F                       # list all objects
X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
$ for i in {X,Y}*(N/^F); do printf "$i "; done; echo  # print empty directories
X X2 Y Y2

Kami juga dapat memeriksa objek yang ditempatkan dalam array. Dengan direktori seperti di atas, misalnya:

$ ls -F                       # list all objects
X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
$ arr=(*)                     # place objects into array "arr"
$ for i in ${^arr}(N/^F); do printf "$i "; done; echo
X X2 Y Y2 Z

Jadi, kita bisa menguji objek yang mungkin sudah diatur dalam parameter array.

Perhatikan bahwa kode pada blok for jelas dijalankan pada setiap direktori. Jika ini tidak diinginkan maka Anda cukup mengisi parameter array dan kemudian beroperasi pada parameter itu:

$ for i in *(NF) ; do full_directories+=($i) ; done
$ do_something $full_directories

Penjelasan

Untuk pengguna zsh ada kualifikasi glob (F) (lihat man zshexpn), yang cocok dengan direktori "penuh" (tidak kosong):

$ mkdir X Y
$ touch Y/.f        # Y is now not empty
$ touch f           # create a regular file
$ ls -dF *          # list everything in the current directory
f X/ Y/
$ ls -dF *(F)       # will list only "full" directories
Y/

Kualifikasi (F) mencantumkan objek yang cocok: adalah direktori DAN tidak kosong. Jadi, (^F) cocok: bukan direktori OR kosong. Jadi, (^F) sendiri juga akan mencantumkan file biasa, misalnya. Jadi, seperti yang dijelaskan pada halaman manual zshexp, kita juga memerlukan kualifikasi glob (/), yang hanya mencantumkan direktori:

$ mkdir X Y Z
$ touch X/f Y/.f    # directories X and Y now not empty
$ for i in *(/^F) ; do echo $i ; done
Z

Dengan demikian, untuk memeriksa apakah direktori yang diberikan kosong, Anda dapat menjalankan:

$ mkdir X
$ for i in X(/^F) ; do echo $i ; done ; echo "finished"
X
finished

dan hanya untuk memastikan bahwa direktori tidak kosong tidak akan ditangkap:

$ mkdir Y
$ touch Y/.f
$ for i in Y(/^F) ; do echo $i ; done ; echo "finished"
zsh: no matches found: Y(/^F)
finished

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 bola dunia yang ditemukan. Karena itu kita perlu menekan kemungkinan pesan kesalahan ini dengan kualifikasi glob (N):

$ mkdir Y
$ touch Y/.f
$ for i in Y(N/^F) ; do echo $i ; done ; echo "finished"
finished

Jadi, untuk direktori yang tidak kosong kita membutuhkan kualifikasi (N/^F), yang dapat Anda baca sebagai: "jangan peringatkan saya tentang kegagalan, direktori yang tidak penuh".

Demikian pula, untuk direktori kosong kita memerlukan kualifikasi (NF), yang juga dapat kita baca sebagai: "jangan memperingatkan saya tentang kegagalan, direktori lengkap".

1
Zorawar

Variasi kecil dari Jawaban Bruno :

files=$(ls -1 /some/dir| wc -l)
if [ $files -gt 0 ] 
then
    echo "Contains files"
else
    echo "Empty"
fi

Ini bekerja untuk saya

1
loockass
if ls /some/dir/* >/dev/null 2>&1 ; then echo "huzzah"; fi;
0
Toby

Saya terkejut panduan wooledge pada direktori kosong belum saya sebutkan. Panduan ini, dan semuanya dari wooledge, harus dibaca untuk pertanyaan jenis Shell.

Dari catatan dari halaman itu:

Jangan pernah mencoba mem-parsing output. Bahkan ls -A solusi dapat pecah (mis. Pada HP-UX, jika Anda root, ls -A tidak. sesuatu yang sangat bodoh).

Bahkan, orang mungkin ingin menghindari pertanyaan langsung sama sekali. Biasanya orang ingin tahu apakah a direktori kosong karena mereka ingin melakukan sesuatu yang melibatkan file-file di dalamnya, dll. Lihat ke yang lebih besar. pertanyaan. Misalnya, salah satu contoh berbasis penemuan ini mungkin merupakan solusi yang tepat:

   # Bourne
   find "$somedir" -type f -exec echo Found unexpected file {} \;
   find "$somedir" -maxdepth 0 -empty -exec echo {} is empty. \;  # GNU/BSD
   find "$somedir" -type d -empty -exec cp /my/configfile {} \;   # GNU/BSD

Paling umum, semua yang benar-benar dibutuhkan adalah sesuatu seperti ini:

   # Bourne
   for f in ./*.mpg; do
        test -f "$f" || continue
        mympgviewer "$f"
    done

Dengan kata lain, orang yang mengajukan pertanyaan mungkin berpikir tes direktori kosong eksplisit diperlukan untuk menghindari pesan kesalahan seperti mympgviewer: ./*.mpg: Tidak ada file atau direktori seperti itu padahal tidak ada tes semacam itu diperlukan.

0
bishop

Saya akan memilih find:

if [ -z "$(find $dir -maxdepth 1 -type f)" ]; then
    echo "$dir has NO files"
else
    echo "$dir has files"

Ini memeriksa output mencari hanya file di direktori, tanpa melalui subdirektori. Kemudian memeriksa output menggunakan opsi -z yang diambil dari man test:

   -z STRING
          the length of STRING is zero

Lihat beberapa hasil:

$ mkdir aaa
$ dir="aaa"

Dir kosong:

$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty

Hanya dirs di dalamnya:

$ mkdir aaa/bbb
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty

File dalam direktori:

$ touch aaa/myfile
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
$ rm aaa/myfile 

File dalam subdirektori:

$ touch aaa/bbb/another_file
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty
0
fedorqui

Dengan beberapa solusi saya bisa menemukan cara sederhana untuk mengetahui apakah ada file dalam direktori. Ini dapat diperluas dengan lebih banyak dengan perintah grep untuk memeriksa secara khusus file .xml atau .txt dll. Contoh: ls /some/dir | grep xml | wc -l | grep -w "0"

#!/bin/bash
if ([ $(ls /some/dir | wc -l  | grep -w "0") ])
    then
        echo 'No files'
    else
        echo 'Found files'
fi
0
chanaka777

Sejauh ini saya belum melihat jawaban yang menggunakan grep yang saya pikir akan memberikan jawaban yang lebih sederhana (dengan simbol yang tidak terlalu banyak!). Inilah yang akan saya lakukan Memeriksa apakah ada file di direktori menggunakan bourne Shell:

ini mengembalikan jumlah file dalam direktori:

ls -l <directory> | egrep -c "^-"

anda dapat mengisi jalur direktori di mana direktori ditulis. Bagian pertama dari pipa memastikan bahwa karakter pertama dari output adalah "-" untuk setiap file. egrep kemudian menghitung jumlah garis yang dimulai dengan simbol .__ tersebut menggunakan ekspresi reguler. sekarang yang harus Anda lakukan adalah menyimpan nomor yang Anda peroleh dan membandingkannya menggunakan backquotes seperti: 

 #!/bin/sh 
 fileNum=`ls -l <directory> | egrep -c "^-"`  
 if [ $fileNum == x ] 
 then  
 #do what you want to do
 fi

x adalah variabel pilihan Anda.

0
Jecht Tyre

Coba dengan perintah find . Tetapkan direktori yang di-hardcode atau sebagai argumen . Kemudian mulai temukan untuk mencari semua file di dalam direktori . Periksa apakah return of find adalah null . Echo data dari find

#!/bin/bash

_DIR="/home/user/test/"
#_DIR=$1
_FIND=$(find $_DIR -type f )
if [ -n "$_FIND" ]
then
   echo -e "$_DIR contains files or subdirs with files \n\n "
   echo "$_FIND"
else
echo "empty (or does not exist)"
fi
0
GiannakopoulosJ

Jawaban sederhana dengan bash :

if [[ $(ls /some/dir/) ]]; then echo "huzzah"; fi;
0
Thomas Steinbach

Mencampur hal-hal Prune dan jawaban terakhir, saya harus

find "$some_dir" -Prune -empty -type d | read && echo empty || echo "not empty"

yang bekerja untuk jalur dengan spasi juga

0
Laurent G