디렉토리에 파일이 포함되어 있는지 쉘 스크립트에서 확인
쉘 스크립트에서 디렉토리에 파일이 있는지 어떻게 확인합니까?
이것과 비슷한 것
if [ -e /some/dir/* ]; then echo "huzzah"; fi;
그러나 디렉토리에 하나 또는 여러 파일이 포함 된 경우 작동합니다 (위의 파일은 정확히 0 또는 1 파일에서만 작동합니다).
지금까지의 솔루션은 ls
. 다음은 모든 bash 솔루션입니다.
#!/bin/bash
shopt -s nullglob dotglob # To include hidden files
files=(/some/dir/*)
if [ ${#files[@]} -gt 0 ]; then echo "huzzah"; fi
세 가지 최고의 트릭
shopt -s nullglob dotglob; f=your/dir/*; ((${#f}))
이 트릭은 100 % bash
이며 하위 쉘을 호출 (스폰)합니다. 아이디어는 Bruno De Fraine에서 나 왔으며 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
참고 : 빈 디렉토리와 존재하지 않는 디렉토리 사이에는 차이가 없습니다 (제공된 경로가 파일 인 경우에도).
#bash IRC 채널 에 대한 '공식' FAQ에 유사한 대안과 자세한 내용 (및 더 많은 예제)이 있습니다 .
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)" ]
이 트릭은 2007 년에 게시 된 nixCraft의 기사 에서 영감을 얻었습니다 . 2>/dev/null
출력 오류를 억제하려면 추가하십시오 "No such file or directory"
.
참조 앤드류 테일러 의 대답 (2008)와 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
또는 한 줄 bashism 버전 :
[[ $(ls -A your/dir) ]] && echo "contains files" || echo "empty"
참고 : 디렉토리가 존재하지 않을 때 ls
반환 $?=2
됩니다. 그러나 파일과 빈 디렉토리 사이에는 차이가 없습니다.
[ -n "$(find your/dir -prune -empty)" ]
이 마지막 트릭은 phils 의 의견으로 대체되고 개선 된 gravstar 의 답변 에서 영감을 받았습니다 .-maxdepth 0
-prune
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
다음을 사용하는 변형 -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
설명:
find -prune
find -maxdepth 0
적은 문자를 사용하는 것과 유사 합니다.find -empty
빈 디렉토리 및 파일을 인쇄합니다.find -type d
디렉토리 만 인쇄
참고 :[ -n "$(find your/dir -prune -empty)" ]
아래의 단축 버전으로 대체 할 수도 있습니다.
if [ `find your/dir -prune -empty 2>/dev/null` ]
then
echo "empty (directory or file)"
else
echo "contains files (or does not exist)"
fi
이 마지막 코드는 대부분의 경우에 작동하지만 악의적 인 경로가 명령을 표현할 수 있습니다.
다음은 어떻습니까?
if find /some/dir/ -maxdepth 0 -empty | read v; then echo "Empty dir"; fi
이렇게하면 디렉토리 내용의 전체 목록을 생성 할 필요가 없습니다. (가) read
두 출력을 버리고 뭔가를 읽을 경우에만 true로 평가 식을 수 있도록하는 것입니다 (즉,은 /some/dir/
으로 비어 발견된다 find
).
시험:
if [ ! -z `ls /some/dir/*` ]; then echo "huzzah"; fi
# 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
}
많은 파일이있는 디렉토리를 관리하십시오! ls
명령 을 평가하는 데 시간이 걸릴 수 있습니다 .
IMO 최고의 솔루션은
find /some/dir/ -maxdepth 0 -empty
DIR="/some/dir"
if [ "$(ls -A $DIR)" ]; then
echo 'There is something alive in here'
fi
이것의 결과를 비교할 수 있습니까?
ls -A /some/dir | wc -l
# 디렉토리에 숨겨지지 않은 파일이 있는지 확인합니다. # # 사용법 : if isempty "$ HOME"; then echo "Welcome home"; fi # 비었다() { $ 1 / *의 _ief에 대해; 하다 if [-e "$ _ief"]; 그때 반환 1 fi 끝난 반환 0 }
구현 참고 사항 :
for
루프는 외부로 전화 방지ls
과정을. 여전히 모든 디렉토리 항목을 한 번 읽습니다. 이것은 readdir ()을 명시 적으로 사용하는 C 프로그램을 작성해야만 최적화 할 수 있습니다.test -e
루프 내부 변수가있는 경우 빈 디렉토리의 경우 잡는다_ief
값 "somedir / *"를 할당 할 것입니다. 해당 파일이 존재하는 경우에만 함수가 "비어 있지 않음"을 반환합니다.- 이 기능은 모든 POSIX 구현에서 작동합니다. 그러나 Solaris / bin / sh는 해당 범주에 속하지 않습니다. 그것의
test
구현은 지원하지 않습니다-e
플래그.
이것은 정말 늦은 응답 일 수 있지만 여기에 작동하는 해결책이 있습니다. 이 줄은 파일의 존재 만 인식합니다! 디렉토리가 존재하는 경우 오 탐지를 제공하지 않습니다.
if find /path/to/check/* -maxdepth 0 -type f | read
then echo "Files Exist"
fi
이것은 디렉토리가 비어 있는지 또는 비어 있지 않은 경우 포함 된 파일 수를 알려줍니다.
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
빈 디렉토리에 대한 모직 가이드 가 언급되지 않은 것에 놀랐습니다 . 이 가이드와 모든 wooledge는 실제로 쉘 유형 질문에 대해 반드시 읽어야합니다.
해당 페이지에서 주목할 사항 :
ls 출력을 구문 분석하지 마십시오. ls -A 솔루션조차도 망가질 수 있습니다 (예 : HP-UX에서 루트 인 경우 ls -A는 루트가 아닌 경우 수행하는 작업과 정반대를 수행합니다. 그리고 아니요, 믿을 수 없을 정도로 구성 할 수 없습니다. 바보).
사실 직접적인 질문을 아예 피하고 싶을 수도 있습니다. 일반적으로 사람들은 디렉토리가 비어 있는지 여부를 알고 싶어합니다. 그 이유는 파일과 관련된 작업을 수행하기 때문입니다. 더 큰 질문을보십시오. 예를 들어 다음 찾기 기반 예제 중 하나가 적절한 솔루션이 될 수 있습니다.
# 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
가장 일반적으로 필요한 것은 다음과 같습니다.
# Bourne
for f in ./*.mpg; do
test -f "$f" || continue
mympgviewer "$f"
done
즉, 질문을하는 사람은 mympgviewer와 같은 오류 메시지를 피하기 위해 명시적인 빈 디렉토리 테스트가 필요하다고 생각했을 수 있습니다. ./*.mpg : 실제로 그러한 테스트가 필요하지 않은 경우 그러한 파일이나 디렉토리가 없습니다.
dir_is_empty() {
[ "${1##*/}" = "*" ]
}
if dir_is_empty /some/dir/* ; then
echo "huzzah"
fi
라는 이름의 파일이없는 가정 *
에를 /any/dir/you/check
, 그것은에 작업을해야 bash
dash
posh
busybox sh
하고 zsh
필요하지만 (zsh을 위해) unsetopt nomatch
.
성능은 (glob) ls
을 사용 하는 모든 것과 비슷해야합니다. *
노드가 많은 디렉토리에서 느릴 것이라고 생각합니다 ( /usr/bin
3000 개 이상의 파일을 사용하는 경우 그다지 느리지 않음), 모든 디렉토리 / 파일 이름을 할당하기에 충분한 메모리를 사용합니다 (및 그 이상). 모두 인수로 함수에 전달 (해결)되므로 일부 쉘은 인수 수 및 / 또는 인수 길이에 제한이있을 수 있습니다.
디렉토리가 비어 있는지 확인하는 이식 가능한 빠른 O (1) 제로 리소스 방법이 있으면 좋을 것입니다.
최신 정보
위의 버전 is_empty
은 Rich의 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 )
그러나 대신 다음과 같은 것을 생각하고 있습니다.
dir_is_empty() {
[ "$(find "$1" -name "?*" | dd bs=$((${#1}+3)) count=1 2>/dev/null)" = "$1" ]
}
dir이 비어있을 때 인수 및 find 출력과의 후행 슬래시 차이점과 후행 줄 바꿈 (하지만 처리하기 쉽습니다)에 대한 우려가 있습니다. 슬프게도 내 busybox
sh
쇼 find -> dd
에서 출력이 무작위로 잘린 파이프 의 버그 일 수 있습니다 ( 내가 사용한 cat
경우 출력은 항상 동일 dd
하며 인수가 있는 것 같습니다 count
).
Bruno의 대답의 작은 변형 :
files=$(ls -1 /some/dir| wc -l)
if [ $files -gt 0 ]
then
echo "Contains files"
else
echo "Empty"
fi
그것은 나를 위해 작동합니다
ZSH
나는 그 질문이 bash로 표시되었다는 것을 안다. 참고로 zsh 사용자의 경우 :
비어 있지 않은 디렉토리 테스트
foo
비어 있지 않은지 확인하려면 :
$ for i in foo(NF) ; do ... ; done
만약 여기서 foo
비어 있지 상기의 코드 for
블록이 실행된다.
빈 디렉토리 테스트
foo
비어 있는지 확인하려면 :
$ for i in foo(N/^F) ; do ... ; done
foo
비어 있으면 for
블록 의 코드 가 실행됩니다.
노트
foo
위 의 디렉토리를 인용 할 필요는 없었지만 다음과 같은 경우에 그렇게 할 수 있습니다.
$ for i in 'some directory!'(NF) ; do ... ; done
디렉토리가 아니더라도 둘 이상의 객체를 테스트 할 수도 있습니다.
$ 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
디렉토리가 아닌 것은 무시됩니다.
기타
globbing이므로 어떤 glob (또는 중괄호 확장)도 사용할 수 있습니다.
$ 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
배열에 배치 된 객체를 검사 할 수도 있습니다. 위와 같은 디렉토리로 예를 들면 다음과 같습니다.
$ 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
따라서 배열 매개 변수에 이미 설정되어있을 수있는 객체를 테스트 할 수 있습니다.
for
블록 의 코드는 분명히 모든 디렉토리에서 차례로 실행됩니다. 이것이 바람직하지 않은 경우 단순히 배열 매개 변수를 채운 다음 해당 매개 변수에 대해 작업 할 수 있습니다.
$ for i in *(NF) ; do full_directories+=($i) ; done
$ do_something $full_directories
설명
zsh 사용자의 경우 "full"(비어 있지 않은) 디렉토리와 일치 하는 (F)
glob 한정자 (참조 man zshexpn
)가 있습니다.
$ 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/
한정자 (F)
는 다음과 일치하는 객체를 나열합니다. 디렉토리이고 비어 있지 않습니다. 따라서 (^F)
일치 : 디렉토리가 아니거나 비어 있습니다. 따라서 (^F)
예를 들어 혼자서도 일반 파일을 나열합니다. 따라서 zshexp
man 페이지 에 설명 된대로 (/)
디렉토리 만 나열 하는 glob 한정자 가 필요합니다 .
$ 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
따라서 주어진 디렉토리가 비어 있는지 확인하려면 다음을 실행할 수 있습니다.
$ mkdir X
$ for i in X(/^F) ; do echo $i ; done ; echo "finished"
X
finished
비어 있지 않은 디렉토리가 캡처되지 않도록합니다.
$ mkdir Y
$ touch Y/.f
$ for i in Y(/^F) ; do echo $i ; done ; echo "finished"
zsh: no matches found: Y(/^F)
finished
이런! Y
이 비어 있지 않기 때문에 zsh는 (/^F)
( "비어있는 디렉토리")와 일치하는 항목이 없으므로 glob에 일치하는 항목이 없다는 오류 메시지를 표시합니다. 따라서 (N)
glob 한정자를 사용하여 이러한 가능한 오류 메시지를 억제해야합니다 .
$ mkdir Y
$ touch Y/.f
$ for i in Y(N/^F) ; do echo $i ; done ; echo "finished"
finished
따라서 비어 있지 않은 디렉토리의 경우 다음 (N/^F)
과 같이 읽을 수 있는 한정자가 필요합니다 . "충분하지 않은 디렉토리, 실패에 대해 경고하지 마십시오".
비슷하게, 빈 디렉토리의 경우 (NF)
, "실패, 전체 디렉토리에 대해 경고하지 마십시오"라고 읽을 수 있는 한정자가 필요합니다 .
olibre의 답변에서 힌트 (또는 여러 가지)를 취하면 Bash 기능이 좋습니다.
function isEmptyDir {
[ -d $1 -a -n "$( find $1 -prune -empty 2>/dev/null )" ]
}
Because while it creates one subshell, it's as close to an O(1) solution as I can imagine and giving it a name makes it readable. I can then write
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
As for O(1) there are outlier cases: if a large directory has had all or all but the last entry deleted, "find" may have to read the whole thing to determine whether it's empty. I believe that expected performance is O(1) but worst-case is linear in the directory size. I have not measured this.
if ls /some/dir/* >/dev/null 2>&1 ; then echo "huzzah"; fi;
So far I haven't seen an answer that uses grep which I think would give a simpler answer (with not too many weird symbols!). Here is how I would check if any files exist in the directory using bourne shell:
this returns the number of files in a directory:
ls -l <directory> | egrep -c "^-"
you can fill in the directory path in where directory is written. The first half of the pipe ensures that the first character of output is "-" for each file. egrep then counts the number of line that start with that symbol using regular expressions. now all you have to do is store the number you obtain and compare it using backquotes like:
#!/bin/sh
fileNum=`ls -l <directory> | egrep -c "^-"`
if [ $fileNum == x ]
then
#do what you want to do
fi
x is a variable of your choice.
Mixing prune things and last answers, I got to
find "$some_dir" -prune -empty -type d | read && echo empty || echo "not empty"
that works for paths with spaces too
Simple answer with bash:
if [[ $(ls /some/dir/) ]]; then echo "huzzah"; fi;
I would go for find
:
if [ -z "$(find $dir -maxdepth 1 -type f)" ]; then
echo "$dir has NO files"
else
echo "$dir has files"
This checks the output of looking for just files in the directory, without going through the subdirectories. Then it checks the output using the -z
option taken from man test
:
-z STRING
the length of STRING is zero
See some outcomes:
$ mkdir aaa
$ dir="aaa"
Empty dir:
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty
Just dirs in it:
$ mkdir aaa/bbb
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty
A file in the directory:
$ touch aaa/myfile
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
$ rm aaa/myfile
A file in a subdirectory:
$ touch aaa/bbb/another_file
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty
Try with command find. Specify the directory hardcoded or as argument. Then initiate find to search all files inside the directory. Check if return of find is null. Echo the data of 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
With some workaround I could find a simple way to find out whether there are files in a directory. This can extend with more with grep commands to check specifically .xml or .txt files etc. Ex : 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
to test a specific target directory
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;
I dislike the ls - A
solutions posted. Most likely you wish to test if the directory is empty because you don't wish to delete it. The following does that. If however you just wish to log an empty file, surely deleting and recreating it is quicker then listing possibly infinite files?
This should work...
if ! rmdir ${target}
then
echo "not empty"
else
echo "empty"
mkdir ${target}
fi
Works well for me this (when dir exist):
some_dir="/some/dir with whitespace & other characters/"
if find "`echo "$some_dir"`" -maxdepth 0 -empty | read v; then echo "Empty dir"; fi
With full check:
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
참고URL : https://stackoverflow.com/questions/91368/checking-from-shell-script-if-a-directory-contains-files
'Programming' 카테고리의 다른 글
정의되지 않은 메서드 mysqli_stmt :: get_result 호출 (0) | 2020.08.10 |
---|---|
전체 라인을 sed로 바꾸는 방법? (0) | 2020.08.10 |
프로그래밍 방식으로 UITableView 섹션 제목을 설정하는 방법 (iPhone / iPad)? (0) | 2020.08.10 |
세션 상태 서버에 세션 상태 요청을 할 수 없습니다. (0) | 2020.08.10 |
개인 생성자에 테스트 커버리지를 추가하는 방법은 무엇입니까?PHP : stdClass 객체 계산 (0) | 2020.08.10 |