Kiểm tra từ tập lệnh shell nếu một thư mục chứa tệp


116

Từ tập lệnh shell, làm cách nào để kiểm tra xem thư mục có chứa tệp không?

Một cái gì đó tương tự như thế này

if [ -e /some/dir/* ]; then echo "huzzah"; fi;

nhưng hoạt động nếu thư mục chứa một hoặc một số tệp (tệp ở trên chỉ hoạt động với chính xác 0 hoặc 1 tệp).


Đối với những gì nó có giá trị ví dụ của bạn tốt làm những gì bạn muốn trong ksh và zsh
Dave Webb

2
@DaveWebb Không, không. Nếu hình cầu mở rộng thành nhiều hơn một từ, kiểm tra zsh báo cáo 'kiểm tra: quá nhiều đối số'.
Jens

"huzzah" có nghĩa là "thư mục không trống".
funroll

Nếu thư mục chỉ chứa một thư mục con trống, thì thư mục đó có được tính là "chứa tệp" không?
Keith Thompson

Câu trả lời:


72

Các giải pháp cho đến nay sử dụng ls. Đây là một giải pháp tất cả các bash:

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

8
miễn là bạn nhớ đặt các tùy chọn trở lại giá trị ban đầu của chúng ở cuối tập lệnh :)
Jean

Đây là một phiên bản được cải thiện đôi chút rằng sẽ chăm sóc của đặt lại các thiết lập bash: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;
user123444555621

12
Tại sao không sử dụng một subshell để thiết lập lại các cài đặt:files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*)
teambob

7
@teambob nếu sử dụng sub-shell: files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*) thì câu lệnh if sẽ chuyển thành if [ ${#files} -gt 0 ];hoặc có thể bạn quên dấu () xung quanh lệnh sub-shell? files=($(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*))
stutyhk

2
@stoutyhk $ (...) khôi phục cài đặt, không yêu cầu vỏ con riêng biệt. Sử dụng $ (...) sinh ra một phiên bản mới của shell. Môi trường của phiên bản mới này sẽ bị loại bỏ sau khi lệnh kết thúc. Chỉnh sửa: Đã tìm thấy một tham chiếu tldp.org/LDP/abs/html/commandsub.html "Thay thế lệnh gọi một vỏ con."
teambob

140

Ba thủ thuật hay nhất


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

Thủ thuật này là 100% bashvà gọi (sinh ra) một trình bao phụ. Ý tưởng là của Bruno De Fraine và được cải thiện bởi nhận xét của 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

Lưu ý: không có sự khác biệt giữa thư mục trống và thư mục không tồn tại (và ngay cả khi đường dẫn được cung cấp là một tệp).

Có một giải pháp thay thế tương tự và nhiều chi tiết hơn (và nhiều ví dụ khác) trên Câu hỏi thường gặp 'chính thức' cho kênh #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)" ]

Thủ thuật này được lấy cảm hứng từ bài báo của nixCraft được đăng vào năm 2007. Thêm 2>/dev/nullđể loại bỏ lỗi đầu ra "No such file or directory".
Xem thêm câu trả lời của Andrew Taylor (2008) và câu trả lời của gr8can8dian (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

hoặc phiên bản bashism một dòng:

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

Lưu ý: ls trả về $?=2khi thư mục không tồn tại. Nhưng không có sự khác biệt giữa một tệp và một thư mục trống.


[ -n "$(find your/dir -prune -empty)" ]

Bí quyết cuối cùng này được lấy cảm hứng từ câu trả lời của gravstar nơi -maxdepth 0được thay thế bằng -prunevà cải thiện bằng cách Phils bình luận 's.

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

một biến thể sử dụng -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

Giải trình:

  • find -prunetương tự như find -maxdepth 0việc sử dụng ít ký tự hơn
  • find -empty in các thư mục và tệp trống
  • find -type d chỉ in thư mục

Lưu ý: Bạn cũng có thể thay thế [ -n "$(find your/dir -prune -empty)" ]chỉ bằng phiên bản rút gọn bên dưới:

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

Mã cuối cùng này hoạt động trong hầu hết các trường hợp nhưng lưu ý rằng các đường dẫn độc hại có thể thể hiện một lệnh ...


2
Tôi nghĩ rằng bạn có thể đơn giản hóa tùy chọn tìm [ -n "$(find "your/dir" -prune -empty)" ]để tránh sự lặp lại của đường dẫn thư mục.
phils

Trong khi sử dụng if [ ``ls -A your/dir`` ]trong một tập lệnh, tôi đã đi đến kết luận rằng nó hoạt động tốt cho một thư mục có 0, 1 hoặc 2 thư mục con, nhưng không thành công cho một thư mục có nhiều hơn 2 thư mục con. line 17: [: 20150424-002813: unary operator expectedđâu 20150424-002813là một trong những tên thư mục. Vỏ được sử dụng là /bin/bash/. Cuối cùng tôi đã đổi nó thànhls "$destination" | tail -1
Christophe De Troyer

Xin chào @ChristopheDeTroyer Tôi không thể tái tạo sự cố của bạn. Về phía tôi if [ ``ls -A my/dir`` ]thoát khỏi lỗi bash: [: -A: binary operator expected. Đã thử nghiệm trên phiên bản bash 4.1.2 và 4.2.53.
olibre

1
Chà, tôi chủ yếu có động cơ bình luận vì nhận thấy sự không nhất quán (vì -nbiến thể nằm trong tiêu đề nhưng sau đó không có trong đoạn bên dưới). Vì vậy, có, nó ổn.
maxschlepzig

1
Tôi đang sử dụng giải pháp -n của bạn, kịch bản của tôi vẫn còn phàn nàn về điều này ls: cannot access '/path': No such file or directory. Có cách nào tôi có thể chặn thông báo này không? Tôi muốn thất bại âm thầm ở đó.
Freedo

48

Làm thế nào về những điều sau:

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

Bằng cách này không cần tạo một danh sách đầy đủ các nội dung của thư mục. Cả readhai đều để loại bỏ đầu ra và làm cho biểu thức được đánh giá thành true chỉ khi một thứ gì đó được đọc (tức /some/dir/là được tìm thấy trống bởi find).


3
hoặc đơn giảnfind /some/dir/ -maxdepth 0 -empty -exec echo "huzzah" \;
doubleDown

5
+1 Đây là giải pháp thanh lịch nhất. Nó không liên quan đến việc phân tích cú pháp lsđầu ra và nó không dựa vào các tính năng của shell không mặc định.

7
Tuy nhiên, nó dựa trên các tiêu chuẩn không chuẩn -maxdepthvà các -emptycuộc bầu cử sơ bộ.
chepner

21

Thử:

if [ ! -z `ls /some/dir/*` ]; then echo "huzzah"; fi

Điều này hiệu quả với tôi, nhưng tôi không thể định dạng tin nhắn d * mn này !!! <br> xuất tmp = /bin/ls <some_dir>/* 2> /dev/nullif [! -z "$ tmp"]; then echo Something is there fi
AndrewStone

1
Đối với những kẻ ngốc Bash như tôi, nếu bạn muốn kiểm tra ngược lại - rằng thư mục có trống không - chỉ cần sử dụng if [-z ls /some/dir/*]; sau đó echo "huzzah"; fi
Chris Moschini,

4
Bạn có thể sử dụng -nthay vì ! -z(cả hai đều tương đương, nhưng tại sao không sử dụng dạng ngắn hơn khi nó tồn tại).
n.st

Nếu ZSH ví dụ này ném một lỗi, ý tưởng là không có lỗi được ném ra ... BigGray% if [ ! -z ls / some / dir / * `]; sau đó echo "huzzah"; fi zsh: không tìm thấy kết quả phù hợp nào: / some / dir / * `
Hvisage 20/02/17

không làm việc cho tôi mà không ngoặc kép quanh ls...trong bash
letmutx

15
# 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
}

15

Hãy cẩn thận với các thư mục có rất nhiều tệp! Có thể mất một chút thời gian để đánh giá lslệnh.

IMO giải pháp tốt nhất là giải pháp sử dụng

find /some/dir/ -maxdepth 0 -empty

8
DIR="/some/dir"
if [ "$(ls -A $DIR)" ]; then
     echo 'There is something alive in here'
fi

6

Bạn có thể so sánh đầu ra của điều này?

 ls -A /some/dir | wc -l

4
# Kiểm tra xem một thư mục có chứa bất kỳ tệp không ẩn nào không.
#
# cách sử dụng: if isempty "$ HOME"; sau đó echo "Chào mừng bạn về nhà"; fi
#
isempty () {
    cho _ief trong $ 1 / *; làm
        if [-e "$ _ief"]; sau đó
            trả lại 1
        fi
    làm xong
    trả về 0
}

Một số lưu ý khi triển khai:

  • Các forvòng tránh một cuộc gọi đến một bên ngoài lsquá trình. Nó vẫn đọc tất cả các mục trong thư mục một lần. Điều này chỉ có thể được tối ưu hóa bằng cách viết một chương trình C sử dụng readdir () một cách rõ ràng.
  • Các test -ebên trong vòng lặp bắt trường hợp của một thư mục rỗng, trong trường hợp này biến _iefsẽ được gán giá trị "somedir / *". Chỉ khi tệp đó tồn tại thì hàm sẽ trả về "nonempty"
  • Chức năng này sẽ hoạt động trong tất cả các triển khai POSIX. Nhưng hãy lưu ý rằng Solaris / bin / sh không thuộc loại đó. Việc testtriển khai nó không hỗ trợ -ecờ.

1
Điều này sẽ bỏ qua các tệp dotfiles trong thư mục nếu dotglobkhông được đặt -shopt -s dotglob
l0b0

4

Điều này cho tôi biết liệu thư mục có trống hay không, số lượng tệp mà nó chứa.

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

Bất cứ ai có thể giải thích cho tôi lý do tại sao tôi bị từ chối? Nếu tôi đang viết craps, tôi muốn biết tại sao;)
Daishi

1
Tôi không phản đối điều này, nhưng có thể đoán đó là vì bạn đang phân tích cú pháp đầu ra củals .
Toby Speight

là bài viết được liên kết không rõ ràng? Nếu vậy, hãy gửi email cho tác giả (không phải tôi).
Toby Speight

1
@TobySpeight Tôi thấy vấn đề. Nhưng trong trường hợp này, tôi đang đếm các dòng không liệt kê chúng. Nó chỉ cho kết quả sai nếu tên tệp chứa một dòng mới. Và nếu tên tệp chứa các dòng mới, thì một thứ quan trọng hơn nhiều phải có ở đâu đó;)
Daishi

3

Đây có thể là một phản hồi thực sự muộn nhưng đây là một giải pháp hiệu quả. Dòng này chỉ ghi nhận sự tồn tại của tệp! Nó sẽ không cung cấp cho bạn một kết quả dương tính giả nếu các thư mục tồn tại.

if find /path/to/check/* -maxdepth 0 -type f | read
  then echo "Files Exist"
fi

2
dir_is_empty() {
   [ "${1##*/}" = "*" ]
}

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

Giả sử bạn không có tệp có tên *trong /any/dir/you/checkđó, tệp sẽ hoạt động bash dash posh busybox shzshnhưng (đối với zsh) yêu cầu unsetopt nomatch.

Hiệu suất phải được so sánh với bất kỳ cách lssử dụng nào *(toàn cầu), tôi đoán sẽ chậm trên các thư mục có nhiều nút (của tôi/usr/bin với hơn 3000 tệp đã không chậm như vậy), sẽ sử dụng ít nhất đủ bộ nhớ để phân bổ tất cả các dirs / tên tệp (và hơn thế nữa) vì tất cả chúng đều được truyền (giải quyết) cho hàm dưới dạng đối số, một số trình bao có thể có giới hạn về số lượng đối số và / hoặc độ dài của đối số.

Một cách di động nhanh O (1) 0 tài nguyên để kiểm tra xem một thư mục có trống hay không sẽ rất hay.

cập nhật

Phiên bản trên không tính đến các tệp / dirs ẩn, trong trường hợp cần phải kiểm tra thêm, chẳng hạn như thủ thuật is_emptyfrom Rich's sh (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 )

Nhưng, thay vào đó, tôi đang nghĩ về một thứ như thế này:

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

Một số lo ngại về sự khác biệt giữa dấu gạch chéo so với đối số và kết quả tìm thấy khi dir trống và các dòng mới theo sau (nhưng điều này sẽ dễ dàng xử lý), thật đáng buồn trong busybox shchương trình của tôi có lẽ là một lỗi trên find -> ddđường ống với đầu ra bị cắt ngẫu nhiên ( nếu tôi đã sử dụng catđầu ra luôn luôn giống nhau, dường như là ddvới đối số count).


Tôi thích giải pháp di động. Tôi đến để đưa ra câu trả lời tương tự. Tôi đã viết nó theo cách khác (trả về 2 nếu không phải là một thư mục). Ngoài ra, các giải pháp di động này có lợi thế là không gọi bất kỳ chương trình bên ngoài nào, điều này có thể được coi là một điểm cộng cho các hệ thống bị ràng buộc hoặc nhúng. Tôi chỉ lo lắng rằng việc sử dụng "()" có thể tạo ra một quy trình con mới (hoặc ít nhất buộc phải sao chép môi trường và nội dung rồi chuyển trở lại). Hãy xem phần này: is_empty () {_d = "$ {1: -.}"; [! -d "$ {_ d}"] && return 2; set - "$ {_ d}" / * "$ {_ d}" /.[!.]* "$ {_ d}" /..?*; ["$ { }" = "$ {_ d} / $ {_ d} /. [!.] * $ {_ d} /..?*"]; };
Diego Augusto Molina

@DiegoAugustoMolina Gần đây trong một dự án, tôi đã phải thực hiện lại bài kiểm tra này, nếu một thư mục trống, lúc đầu tôi sử dụng python, sau đó vì thực tế tôi đã cài đặt python chỉ cho điều đó, tôi đã thực hiện kiểm tra trong c, việc triển khai là cực đoan banality, tôi tự hỏi tại sao nó không bao giờ được thêm vào như là một thử nghiệm hoặc như một lệnh độc lập
Alex

1
Gần đây tôi cũng đang cần một giải pháp cho vấn đề này cho một hệ thống (thực sự) bị hạn chế. Tôi thậm chí còn tối ưu hóa một chút mã trước đó để không sử dụng thêm biến nào cả. Mặc dù vậy, một lớp lót trông có vẻ khó hiểu và xấu xí nhưng tuyệt vời. Phục vụ bản thân:is_empty(){ [ ! -d "${1}" ] && return 2;set -- "${1}" "${1}"/* "${1}"/.[!.]* "${1}"/..?*;[ "${*}" = "${1} ${1}/* ${1}/.[!.]* ${1}/..?*" ]; };
Diego Augusto Molina

2

ZSH

Tôi biết câu hỏi đã được đánh dấu là bash; nhưng, chỉ để tham khảo, cho người dùng zsh :

Kiểm tra thư mục không trống

Để kiểm tra xem có footrống không:

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

trong đó, nếu fookhông trống, mã trong forkhối sẽ được thực thi.

Kiểm tra thư mục trống

Để kiểm tra xem foocó trống không:

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

trong đó, nếu footrống, mã trong forkhối sẽ được thực thi.

Ghi chú

Chúng tôi không cần phải trích dẫn thư mục fooở trên, nhưng chúng tôi có thể làm như vậy nếu chúng tôi cần:

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

Chúng tôi cũng có thể kiểm tra nhiều hơn một đối tượng, ngay cả khi nó không phải là một thư mục:

$ 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

Bất cứ thứ gì không phải là thư mục sẽ bị bỏ qua.

Bổ sung

Vì chúng ta đang hình cầu, nên chúng ta có thể sử dụng bất kỳ hình cầu nào (hoặc mở rộng dấu ngoặc nhọn):

$ 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

Chúng ta cũng có thể kiểm tra các đối tượng được đặt trong một mảng. Với các thư mục như trên, ví dụ:

$ 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

Do đó, chúng ta có thể kiểm tra các đối tượng có thể đã được đặt trong một tham số mảng.

Lưu ý rằng mã trong forkhối hiển nhiên được thực thi lần lượt trên mọi thư mục. Nếu điều này không mong muốn thì bạn có thể chỉ cần điền một tham số mảng và sau đó thao tác trên tham số đó:

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

Giải trình

Đối với người dùng zsh, có (F)vòng loại toàn cầu (xem man zshexpn), phù hợp với các thư mục "đầy đủ" (không trống):

$ 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/

Bộ định tính (F)liệt kê các đối tượng phù hợp: là một thư mục VÀ không trống. Vì vậy, (^F)phù hợp với: không một thư mục HOẶC trống. Vì vậy, (^F)một mình cũng sẽ liệt kê các tệp thông thường, chẳng hạn. Do đó, như đã giải thích trên zshexptrang man, chúng ta cũng cần bộ định lượng toàn (/)cầu, chỉ liệt kê các thư mục:

$ 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

Do đó, để kiểm tra xem một thư mục nhất định có trống không, do đó bạn có thể chạy:

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

và chỉ để đảm bảo rằng một thư mục không trống sẽ không bị bắt:

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

Giáo sư! Vì Ykhông trống, zsh không tìm thấy kết quả phù hợp nào cho (/^F)("thư mục trống") và do đó đưa ra thông báo lỗi nói rằng không tìm thấy kết quả phù hợp nào cho toàn cầu. Do đó, chúng tôi cần loại bỏ các thông báo lỗi có thể có này bằng bộ định lượng toàn (N)cầu:

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

Vì vậy, đối với các thư mục trống, chúng ta cần định tính (N/^F), mà bạn có thể đọc là: "không cảnh báo tôi về lỗi, thư mục không đầy".

Tương tự như vậy, đối với các thư mục không trống, chúng ta cần định tính (NF), tương tự như vậy chúng ta có thể đọc là: "không cảnh báo tôi về lỗi, các thư mục đầy đủ".


1

Tôi rất ngạc nhiên khi hướng dẫn về lenedge trên các thư mục trống không được đề cập đến. Hướng dẫn này, và tất cả các lenedge thực sự, là phải đọc cho các câu hỏi loại shell.

Lưu ý từ trang đó:

Không bao giờ cố gắng phân tích cú pháp đầu ra ls. Ngay cả các giải pháp của ls -A cũng có thể phá vỡ (ví dụ: trên HP-UX, nếu bạn là root, ls -A hoàn toàn ngược lại với những gì nó làm nếu bạn không root - và không, tôi không thể tạo ra thứ gì đó cực kỳ ngốc nghếch).

Trên thực tế, người ta có thể muốn tránh hoàn toàn câu hỏi trực tiếp. Thông thường mọi người muốn biết liệu một thư mục có trống hay không vì họ muốn làm điều gì đó liên quan đến các tệp trong đó, v.v. Hãy xem câu hỏi lớn hơn. Ví dụ: một trong những ví dụ dựa trên kết quả tìm kiếm này có thể là giải pháp thích hợp:

   # 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

Thông thường nhất, tất cả những gì thực sự cần thiết là những thứ như sau:

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

Nói cách khác, người đặt câu hỏi có thể nghĩ rằng cần phải kiểm tra thư mục trống rõ ràng để tránh thông báo lỗi như mympgviewer: ./*.mpg: Không có tệp hoặc thư mục nào như vậy trong khi thực tế không cần kiểm tra như vậy.



1

Lấy một gợi ý (hoặc một vài) từ câu trả lời của olibre, tôi thích một hàm Bash:

function isEmptyDir {
  [ -d $1 -a -n "$( find $1 -prune -empty 2>/dev/null )" ]
}

Bởi vì trong khi nó tạo ra một vỏ con, nó gần giống với giải pháp O (1) như tôi có thể tưởng tượng và đặt tên cho nó khiến nó có thể đọc được. Sau đó tôi có thể viết

if isEmptyDir somedir
then
  echo somedir is an empty directory
else
  echo somedir does not exist, is not a dir, is unreadable, or is  not empty
fi

Đối với O (1) có những trường hợp ngoại lệ: nếu một thư mục lớn đã bị xóa tất cả hoặc tất cả trừ mục nhập cuối cùng, thì "find" có thể phải đọc toàn bộ để xác định xem nó có trống không. Tôi tin rằng hiệu suất dự kiến ​​là O (1) nhưng trường hợp xấu nhất là tuyến tính trong kích thước thư mục. Tôi đã không đo lường điều này.


0

Cho đến nay tôi vẫn chưa thấy một câu trả lời nào sử dụng grep mà tôi nghĩ sẽ đưa ra một câu trả lời đơn giản hơn (không có quá nhiều ký hiệu kỳ lạ!). Đây là cách tôi sẽ kiểm tra xem có tệp nào tồn tại trong thư mục bằng cách sử dụng bourne shell không:

điều này trả về số lượng tệp trong một thư mục:

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

bạn có thể điền vào đường dẫn thư mục nơi thư mục được viết. Nửa đầu của đường ống đảm bảo rằng ký tự đầu tiên của đầu ra là "-" cho mỗi tệp. Sau đó, egrep đếm số dòng bắt đầu bằng ký hiệu đó bằng cách sử dụng biểu thức chính quy. bây giờ tất cả những gì bạn phải làm là lưu trữ số bạn có được và so sánh nó bằng cách sử dụng các dấu ngoặc kép như:

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

x là một biến do bạn chọn.


0

Trộn những thứ sơ lược và câu trả lời cuối cùng, tôi phải

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

điều đó cũng hoạt động cho các đường dẫn có khoảng trắng


0

Câu trả lời đơn giản với bash :

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

0

Tôi sẽ đi cho find:

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

Điều này kiểm tra kết quả của việc chỉ tìm kiếm các tệp trong thư mục mà không cần đi qua các thư mục con. Sau đó, nó kiểm tra đầu ra bằng cách sử dụng -ztùy chọn được lấy từ man test:

   -z STRING
          the length of STRING is zero

Xem một số kết quả:

$ mkdir aaa
$ dir="aaa"

Dir trống:

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

Chỉ cần đào sâu trong đó:

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

Một tệp trong thư mục:

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

Một tệp trong một thư mục con:

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

0

Với một số giải pháp, tôi có thể tìm thấy một cách đơn giản để tìm xem có tệp trong thư mục hay không. Điều này có thể mở rộng thêm với các lệnh grep để kiểm tra cụ thể các tệp .xml hoặc .txt, v.v. Ví dụ: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

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

Tôi thích cái này vì không có dấu ngoặc kép hoặc dấu ngoặc nhọn cho lệnh.
Dave Webb 18-08

Cẩn thận không sử dụng điều này nếu bạn đặt nullglob, vì sau đó lslệnh sẽ thành công.
Steve Kehlet 12/10/12

Sẽ không hoạt động trong mọi môi trường trong trường hợp thư mục có tệp chấm.
Diego Augusto Molina

-1

để kiểm tra một thư mục đích cụ thể

if [ -d $target_dir ]; then
    ls_contents=$(ls -1 $target_dir | xargs); 
    if [ ! -z "$ls_contents" -a "$ls_contents" != "" ]; then
        echo "is not empty";
    else
        echo "is empty";
    fi;
else
    echo "directory does not exist";
fi;

-1

Hãy thử với lệnh tìm. Chỉ định thư mục được mã hóa cứng hoặc làm đối số. Sau đó bắt đầu tìm để tìm kiếm tất cả các tệp bên trong thư mục. Kiểm tra xem kết quả tìm thấy có giá trị không. Cung cấp dữ liệu tìm thấy

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

Nếu thư mục có các thư mục trống hoặc các tệp không thông thường (ổ cắm, thiết bị char, liên kết tượng trưng, ​​v.v.) bên trong thì điều này sẽ không hoạt động. Thư mục sẽ được báo cáo là trống.
Diego Augusto Molina

@DiegoAugustoMolina nếu tôi hiểu đúng trong câu hỏi là chúng tôi đang tìm cách kiểm tra xem tệp có tồn tại hay không (dưới dạng tệp theo nghĩa đen) mà đối số -f đã được sử dụng. nhưng ý kiến ​​của bạn vẫn đúng.
igiannak

-2

Tôi không thích các ls - Agiải pháp được đăng. Nhiều khả năng bạn muốn kiểm tra xem thư mục có trống không vì bạn không muốn xóa nó. Sau đây làm điều đó. Tuy nhiên, nếu bạn chỉ muốn ghi lại một tệp trống, chắc chắn việc xóa và tạo lại nó sẽ nhanh hơn sau đó liệt kê các tệp có thể là vô hạn?

Điều này sẽ hoạt động ...

if !  rmdir ${target}
then
    echo "not empty"
else
    echo "empty"
    mkdir ${target}
fi

4
Điều này không hoạt động nếu người dùng không có quyền ghi vào ${target}/...
Jens

Chỉ là một ý tưởng tồi khi làm cho một bài kiểm tra bị phá hủy. Trong số những thứ khác, nó giới thiệu các điều kiện chủng tộc.
4dummies

-2

Hoạt động tốt cho tôi điều này (khi dir tồn tại):

some_dir="/some/dir with whitespace & other characters/"
if find "`echo "$some_dir"`" -maxdepth 0 -empty | read v; then echo "Empty dir"; fi

Với kiểm tra đầy đủ:

if [ -d "$some_dir" ]; then
  if find "`echo "$some_dir"`" -maxdepth 0 -empty | read v; then echo "Empty dir"; else "Dir is NOT empty" fi
fi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.