Bash 스크립팅 : 빈 디렉토리 테스트


95

디렉토리에 파일이 없는지 테스트하고 싶습니다. 그렇다면 일부 처리를 건너 뛸 것입니다.

나는 다음을 시도했다.

if [ ./* == "./*" ]; then
    echo "No new file"
    exit 1
fi

다음과 같은 오류가 발생합니다.

line 1: [: too many arguments

해결책 / 대안이 있습니까?


답변:


121
if [ -z "$(ls -A /path/to/dir)" ]; then
   echo "Empty"
else
   echo "Not Empty"
fi

또한 디렉토리가 이전에 존재하는지 확인하는 것이 좋습니다.


11
사용하지 마십시오 &&||동시에! 경우 echo "Not Empty"에 실패, echo "Empty"실행됩니다! 시도하십시오 echo "test" && false || echo "fail"! 그렇습니다. 나는 echo실패하지 않을 것입니다. 그러나 다른 명령을 바꾸면 놀라운 일이 될 것입니다!
uzsolt

4
위의 코드가 작동하지 않는 경우 하나 이상의 예를 제공해주세요. 구체적 으로이 코드는 절대적으로 정확합니다. 나는
asker가

3
[ "$(ls -A /)" ] && touch /non-empty || echo "Empty"-파일 이름이 비어있는 비어 있지 않은 디렉토리를 "표시"하려는 경우 non-empty실패하고 "빈"이 인쇄됩니다.
uzsolt

4
touch /empty내 라인 어 where 어 ?
Andrey Atapin

7
아뇨! 이 코드에는 매우 중요한 문제가 있습니다. 그것은해야 if [ -n "$(ls -A /path/to/dir)" ]; then사람이 어딘가에 자신의 서버에이 코드를 붙여 넣 및 해커가이를 악용하는 방법을 파악하기 전에 ... 답을 업데이트하시기 바랍니다. 경우 /path/to/dir비어 있지 않은, 다음 파일 이름이 인수로 전달받을은 할 수 /bin/test있는 분명 아니다. -n문제가 해결 된 논쟁을 추가하십시오 . 감사!
Edward Ned Harvey

21

껍데기를 구할 필요가 없습니다. read와 함께 사용할 수도 있습니다 find. 경우 find의 출력이 비어있는, 당신은 돌아갑니다 false:

if find /some/dir -mindepth 1 | read; then
   echo "dir not empty"
else
   echo "dir empty"
fi

휴대용이어야합니다.


좋은 해결책이지만, 귀하의 echo전화가 잘못된 결과를 반영 한다고 생각합니다 . (Cygwin에서) 내 테스트 find . -mindepth 1 | read에서 비어 있지 않은 디렉토리에 141 오류 코드가 있었고 빈 디렉토리에 0이있었습니다
Lucas Cimon

@LucasCimon 여기에 없습니다 (macOS 및 GNU / Linux). 비어 있지 않은 디렉토리의 경우 read0을 반환하고 비어있는 디렉토리의 경우 1을 반환합니다.
slhck

1
PSA는 작동하지 않습니다set -o pipefail
2시

19
if [ -n "$(find "$DIR_TO_CHECK" -maxdepth 0 -type d -empty 2>/dev/null)" ]; then
    echo "Empty directory"
else
    echo "Not empty or NOT a directory"
fi

정확하고 빠릅니다. 좋은!
l0b0

4
따옴표 (2x)와 테스트 -n가 정확하고 안전 해야합니다 ( 이름에 공백이있는 디렉토리로 테스트하고 이름이 '0 = 1'인 비어 있지 않은 디렉토리로 테스트). ... [ -n "$(find "$DIR_TO_CHECK" -maxdepth 0 -type d -empty 2>/dev/null)" ]; ...
Zrin

1
@ivan_pozdeev 적어도 GNU find에서는 사실이 아닙니다. 당신은 생각할 수 있습니다 grep. serverfault.com/questions/225798/…
블라디미르 판 텔레 예프

작성하는 것이 더 간단하고 find "$DIR_TO_CHECK" -maxdepth 0 -type d -empty | grep .grep의 종료 상태에 의존 할 수 있습니다 . 어떤 방법을 사용하든 이것은이 질문에 대한 정답입니다.
톰 앤더슨

13
#!/bin/bash
if [ -d /path/to/dir ]; then
    # the directory exists
    [ "$(ls -A /path/to/dir)" ] && echo "Not Empty" || echo "Empty"
else
    # You could check here if /path/to/dir is a file with [ -f /path/to/dir]
fi

4
ls 출력을 구문 분석 할 필요가 없으므로 비어 있는지 여부를 확인하십시오. 찾기를 사용하면 나에게 너무 잔인한 느낌이 듭니다.
akostadinov

4

현재 작업 디렉토리 (.)에서 작업을 수행합니다.

[ `ls -1A . | wc -l` -eq 0 ] && echo "Current dir is empty." || echo "Current dir has files (or hidden files) in it."

또는 같은 명령이 더 읽기 쉽도록 세 줄로 나뉩니다.

[ `ls -1A . | wc -l` -eq 0 ] && \
echo "Current dir is empty." || \
echo "Current dir has files (or hidden files) in it."

그냥 교체 ls -1A . | wc -lls -1A <target-directory> | wc -l다른 대상 폴더에서 실행해야하는 경우.

편집 : 나는 교체 -1a와 함께 -1A(@Daniel 설명을 참조)


2
사용하는 ls -A대신. 일부 파일 시스템이없는 ...워드 프로세서에 따라 기호 링크.
Daniel Beck

1
@Daniel에게 감사드립니다. 제안 후 답변을 편집했습니다. "1"도 제거 될 수 있음을 알고 있습니다.
ztank1013

2
아프지 않지만 터미널에 출력하지 않으면 암시 적입니다. 다른 프로그램으로 파이프하기 때문에 중복됩니다.
Daniel Beck

-1확실히 중복됩니다. 하더라도 ls그것이 파이프 될 때 한 줄에 하나의 항목을 인쇄되지 않습니다 다음은 0 개 이상의 라인을 생산하는 경우 검사의 아이디어에 영향을주지 않습니다.
Victor Yarema

3

다음을 사용하십시오.

count="$( find /path -mindepth 1 -maxdepth 1 | wc -l )"
if [ $count -eq 0 ] ; then
   echo "No new file"
   exit 1
fi

이 방법으로의 출력 형식과 독립적입니다 ls. -mindepth디렉토리 자체를 건너 뛰고 -maxdepth하위 디렉토리를 재귀 적으로 방어하여 속도를 높입니다.


물론 이제는 출력 형식 에 의존 wc -l하고 있습니다 find(합리적으로 평범합니다).
Daniel Beck

3

배열 사용하기 :

files=( * .* )
if (( ${#files[@]} == 2 )); then
    # contents of files array is (. ..)
    echo dir is empty
fi

3
아주 좋은 해결책이지만, 필요합니다shopt -s nullglob
xebeche

3
${#files[@]} == 2가정은 루트 디렉토리에 대한 서 있지 않는 (가 비어 있지만, 경우에 당신은 아마 테스트 할 것이다 제한 수도에 대해 알고하지 않습니다 일부 코드).
ivan_pozdeev

3

해킹이지만 배쉬 전용, PID가없는 방법 :

is_empty() {
    test -e "$1/"* 2>/dev/null
    case $? in
        1)   return 0 ;;
        *)   return 1 ;;
    esac
}

이것은 test다음에 하나 이상의 인수가 주어진 경우 내장 종료가 2로 종료 된다는 사실을 이용합니다 -e. 첫째, "$1"/*glob는 bash에 의해 확장됩니다. 결과적으로 파일 당 하나의 인수가 발생합니다. 그래서

  • 파일이 없으면 별표 test -e "$1"*가 확장되지 않으므로 셸은이라는 파일을 시도하여 *1을 반환합니다.

  • ... 실제로 정확히 하나의 파일이있는 경우를 제외하고 *별표는 별표로 확장됩니다. test -e "dir/*", 이번에는 0을 반환합니다. (이 점을 지적 해 주셔서 감사합니다.)

  • 파일이 하나 있으면 test -e "dir/file"실행되어 0을 반환합니다.

  • 그러나 1보다 많은 파일이 있으면 test -e "dir/file1" "dir/file2" bash가 사용 오류로보고합니다 (예 : 2).

case 1 개의 종료 상태가있는 첫 번째 경우 만 성공으로보고되도록 전체 논리를 둘러 쌉니다.

내가 확인하지 않은 가능한 문제 :

  • 허용되는 인수 수보다 많은 파일이 있습니다 .2+ 파일의 경우와 비슷하게 작동 할 수 있습니다.

  • 또는 실제로 이름이 비어있는 파일이 있습니다. 정상적인 OS / FS에서도 가능하지 않습니다.


1
사소한 수정 : dir /에 파일이 없으면 test -e dir/*호출됩니다. dir에서 유일한 파일이 '*'이면 test는 0을 반환합니다. 더 많은 파일이 있으면 2를 반환합니다. 따라서 설명 된대로 작동합니다.
TrueY

당신이 맞습니다, @TrueY, 나는 그것을 대답에 포함 시켰습니다. 감사!
Alois Mahdal

2

FIND (1) (Linux 및 FreeBSD에서)를 사용하면 "-maxdepth 0"을 통해 디렉토리 항목을 비재 귀적으로보고 "-empty"로 비어 있는지 테스트 할 수 있습니다. 이 질문에 적용됩니다 :

if test -n "$(find ./ -maxdepth 0 -empty)" ; then
    echo "No new file"
    exit 1
fi

100 % 휴대 할 수는 없지만 우아합니다.
Craig Ringer

1

가장 좋은 해결책은 다음과 같습니다.

files=$(shopt -s nullglob; shopt -s dotglob; echo /MYPATH/*)
[[ "$files" ]] || echo "dir empty" 

https : //.com/a/91558/520567 덕분에

이것은 누군가에게 도움이되거나 도움이되지 않는 익명의 내 답변 편집입니다.

files=$(shopt -s nullglob dotglob; s=(MYPATH/*); echo ${s[*]}) 
echo "MYPATH contains $files files"

파일 이름에 공백이 있어도 올바르게 작동합니다.


1
if find "${DIR}" -prune ! -empty -exit 1; then
    echo Empty
else
    echo Not Empty
fi

편집 :이 솔루션은 구현을 간략하게 살펴본 후 gnu find와 함께 잘 작동한다고 생각합니다 . 그러나 이것은 netbsd의 find 와 같이 작동하지 않을 있습니다. 실제로, 그것은 stat (2)의 st_size 필드를 사용합니다. 매뉴얼에서는 다음과 같이 설명합니다.

st_size            The size of the file in bytes.  The meaning of the size
                   reported for a directory is file system dependent.
                   Some file systems (e.g. FFS) return the total size used
                   for the directory metadata, possibly including free
                   slots; others (notably ZFS) return the number of
                   entries in the directory.  Some may also return other
                   things or always report zero.

더 간단한 해결책은 다음과 같습니다.

if find "${DIR}" -mindepth 1 -exit 1; then
    echo Empty
else
    echo Not Empty
fi

또한 첫 번째 솔루션의 -prune은 쓸모가 없습니다.

편집 : gnu 찾기에 대한 -exit 없음. 위의 솔루션은 NetBSD의 찾기에 좋습니다. GNU find의 경우 다음과 같이 작동합니다.

if [ -z "`find \"${DIR}\" -mindepth 1 -exec echo notempty \; -quit`" ]; then
    echo Empty
else
    echo Not Empty
fi

GNU findutils 4.6.0 (최신 버전) 에서 찾기 에는 -exit술어 가 없습니다 .
Dennis

0

이것은 모두 훌륭한 것입니다-방금 스크립트로 만들었으므로 현재 디렉토리 아래의 빈 디렉토리를 확인할 수 있습니다. 아래는 'findempty'라는 파일에 넣고 bash가 파일을 찾은 다음 chmod 755를 실행할 수 있도록 경로에 배치해야합니다. 내가 생각하는 특정 요구 사항에 맞게 쉽게 수정할 수 있습니다.

#!/bin/bash
if [ "$#" == "0" ]; then 
find . -maxdepth 1 -type d -exec findempty "{}"  \;
exit
fi

COUNT=`ls -1A "$*" | wc -l`
if [ "$COUNT" == "0" ]; then 
echo "$* : $COUNT"
fi

0

../IN스크립트가 디렉토리 에 있다고 생각하면 directory 에서 파일을 확인하고 처리하는 것이 나를 위해 작동합니다 ../Script.

FileTotalCount=0

    for file in ../IN/*; do
    FileTotalCount=`expr $FileTotalCount + 1`
done

if test "$file" = "../IN/*"
then

    echo "EXITING: NO files available for processing in ../IN directory. "
    exit

else

  echo "Starting Process: Found ""$FileTotalCount"" files in ../IN directory for processing."

# Rest of the Code

0

디렉토리가 존재하고 if 문에서 비어 있지 않은지 테스트하는 것은 어떻습니까?

if [[ -d path/to/dir && -n "$(ls -A path/to/dir)" ]]; then 
  echo "directory exists"
else
  echo "directory doesn't exist"
fi

-1

현재 하나 이외의 디렉토리를 들어, 당신은에 시도하여 비어 있는지 확인 할 수 rmdir있기 때문에, 그것은 rmdir비어 있지 않은 디렉토리에 실패 보장된다. 경우 rmdir성공, 당신은 실제로 단지, 빈 디렉토리가 테스트를 생존하고 싶었 mkdir그것을 다시.

잠깐 동안 존재하지 않는 디렉토리에 의해 혼란스러워 질 수있는 다른 프로세스가있는 경우이 핵을 사용하지 마십시오.

경우 rmdir당신을 위해 작동하지 않습니다, 당신은 잠재적으로 많은 수의 파일, 느린 얻을 및 / 또는 명령 줄 길이 제한으로 실행할 수 쉘 대체 (globbing)에 의존하는 모든 솔루션을 포함 할 수 디렉토리를 테스트 할 수 있습니다. find이 경우 에 사용 하는 것이 좋습니다 . find내가 생각할 수있는 가장 빠른 솔루션은 다음과 같습니다.

is_empty() {
    test -z $(find "$1" -mindepth 1 -printf X -quit)
}

이것은 GNU 및 BSD 버전에서는 작동 find하지만 Solaris 버전에서는 작동 하지 않습니다 find. 당신의 일을 사랑하십시오, 오라클.


좋은 생각이 아닙니다. OP는 단순히 디렉토리가 비어 있는지 테스트하고 싶었습니다.
roaima

-3

디렉토리를 제거하고 오류를 기다릴 수 있습니다. rmdir 은 디렉토리가 비어 있지 않으면 삭제하지 않습니다.

_path="some/path"
if rmdir $_path >/dev/null 2>&1; then
   mkdir $_path        # create it again
   echo "Empty"
else
   echo "Not empty or doesn't exist"
fi

3
-1 역행하는 일종의 코드입니다. rmdir디렉토리를 제거 할 권한이 없으면 실패합니다. 또는 Btrfs 하위 볼륨 인 경우 또는 읽기 전용 파일 시스템에 속하는 경우 그리고 경우는 rmdir실패하지 않고 mkdir실행을 : 이미 제거 디렉토리가 다른 사용자에게 속한 어떤 경우? 표준이 아닌 권한은 어떻습니까? ACL? 확장 된 속성? 모두졌다.
Kamil Maciorowski

글쎄, 나는 배쉬를 배우고 있는데 모든 디렉토리를 반복하는 것보다 더 빠른 방법 일 수 있다고 생각했지만 CPU는 강력하고 안전하지는 않다.
5
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.