디렉토리의 파일 수를 계산하는 가장 좋은 방법은 무엇입니까?


11

ls펑키 한 문자 (공백 \n,, ...)를 깨뜨릴 수 있기 때문에 출력을 구문 분석하는 것이 위험한 경우 디렉토리의 파일 수를 아는 가장 좋은 방법은 무엇입니까?

나는 보통 find이 파싱을 피하기 위해 의존 하지만, 마찬가지로 find mydir | wc -l같은 이유로 깨질 것입니다.

나는 지금 Solaris에서 일하고 있지만 가능한 한 다른 유니스와 다른 쉘에서 이식 가능한 답변을 찾고 있습니다.


3
복제본인지 확실하지 않습니다. 누락 된 것이 있습니까?
— rahmu

1
이것은 중복 될 수 있지만 표시된 질문과는 다릅니다. find파일의 수를 재귀 적으로 가져옵니다 ( -maxdepth 1원치 않는 경우에 사용) . find mydir -maxdepth 1 -type f -printf \\n | wc -l파일 이름의 특수 문자는 처음에 인쇄되지 않으므로 특수 문자를 처리해야합니다.
— Anthon

답변:


16

이 트릭은 어떻습니까?

find . -maxdepth 1 -exec echo \; | wc -l

휴대용로 find하고 wc.


5
작동하지 않습니다 ( n+1데비안 시스템에 파일을 표시 합니다). 또한 일반 파일을 필터링하지 않습니다.
— Chris Down

4
방금 일반적인 예를 들었습니다. 이 작업을 수행하지만, 어떻게 작동하는 것은 당신이 적응 방법에 따라 find사용자의 특정 요구에 명령을. 예, .여기에는를 포함한 모든 디렉토리가 포함됩니다 (결과가로 표시되는 이유 일 수 있음 n+1).
— rozcietrzewiacz

나는이 기술을 매우 영리합니다. 하지만 그렇게 할 수있는 간단한 방법이 없다는 것에 놀랐습니다!
— rahmu

3
@ChrisDown OP는 일반 파일에 대한 필터링을 지정하지 않고 디렉토리의 파일 수를 요청합니다. n + 1 문제를 제거하려면 find . -maxdepth 1 ! -name . -exec echo \; | wc -l; 일부 이전 버전에는 find없습니다 -not.
— Arcege

3
참고 -maxdepth표준되지 않습니다 (지금 또한 몇 가지 다른 구현에서 지원하는 GNU 확장).
— Stéphane Chazelas

11

외부 유틸리티없이 루프를 사용하거나 루프를 사용하지 마십시오.

shopt -s dotglob
files=(*)
echo ${#files[@]}

KSH에서 교체 shopt -s dotglob로 FIGNORE=.?(.). zsh에서로 바꾸 setopt glob_dots거나 shopt통화를 제거 하고을 사용하십시오 files=(*(D)). 또는 도트 파일을 포함하지 않으려면 그냥 줄을 삭제하십시오. 점 파일에 관심이없는 경우 :

set -- *
echo $#

도트 파일을 포함하려면 다음을 수행하십시오.

set -- *
if [ -e "$1" ]; then c=$#; else c=0; fi
set .[!.]*
if [ -e "$1" ]; then c=$((c+$#)); fi
set ..?*
if [ -e "$1" ]; then c=$((c+$#)); fi
echo $c

2
첫 번째 예 는 활성화되지 않은 1경우 빈 디렉토리 를 인쇄 합니다 nullglob. zsh a=(*(DN));echo ${#a}에서 N( nullglob) 한정자를 사용하면 빈 디렉토리에 오류가 발생하지 않습니다.
— nisetama

8
find . ! -name . -prune -print | grep -c /

80 년대 이후 시스템에 이식성이 뛰어나야합니다.

모든 디렉토리 항목을 제외한 카운트 그 .와 ..현재 디렉토리이다.

서브 디렉토리의 파일도 계산하려면 다음을 수행하십시오.

find .//. ! -name . | grep -c //

(필요하지 않기 때문에 Unix V6 (1975)에도 이식 가능해야 함 -prune)


이 페이지에서 드문 휴대용 답변 중 하나입니다.
— xhienne

어제이 대답은 현재 디렉토리 ( find dirname ! -name dirname -prune -print) 이외의 디렉토리에서도 잘 작동한다는 것을 알았습니다 . 그 이후로 (계산에 더 일반적으로 사용되는) grep -c /대신 사용해야 할 특별한 이유가 있는지 궁금합니다 wc -l.
— Anthony Geoghegan

1
find dirname ! -name dirname그 안에 다른 디렉토리가 있으면 작동하지 않습니다 dirname. 를 사용하는 것이 좋습니다 find dirname/. ! -name .. wc -l줄 수를 세고, 줄 바꿈 문자가 파일 이름에서와 같이 유효하므로 파일 이름을 여러 줄로 만들 수 있습니다.
— Stéphane Chazelas

6

시험:

ls -b1A | wc -l

은 -b인쇄 할 수없는 문자를 가지며 , 및 -A파일을 제외한 모든 파일을 표시합니다 (파이프의 기본값이지만 명시 적으로 좋습니다)....

우리가 더 높은 수준의 스크립팅 언어를 포함하는 한, 파이썬에서 한 줄짜리가 있습니다.

python -c 'import os; print len(os.listdir(os.sep))'

또는 완전한 '찾기'가있는 경우 :

python -c 'import os; print len([j for i in os.walk(os.sep) for j in i[1]+i[2]])'

1

Yoc는 이러한 구성을 사용할 수 있습니다.

I=0; for i in * ; do ((I++)); done ; echo $I

그러나 Argument list too long.디렉토리에 파일이 너무 많은 경우 와 같이 오류 가 발생할 수 있습니다. 그러나 100 억 개의 파일이있는 디렉토리에서 테스트했으며 잘 작동했습니다.


3
쉘이 파일을 확장하도록 구성되어 있지 않으면 숨겨진 파일에 대해서는 작동하지 않습니다 *.
— Lekensteyn

gnu find . -maxdepth 1 -type f | wc -l
— Nikhil Mulley

4
@Rush :이 명령은 "arg list를 너무 길게"올릴 수 없습니다. 즉에서만 때문에 결코 (외부 명령으로 일어나지 않는다 for.
— enzotib

1

상대적으로 이식성이 좋은 펄을 고려 했습니까?

다음과 같은 것 :

use File::Find;

$counter = 0;

sub wanted { 
  -f && ++$counter
}

find(\&wanted, @directories_to_search);
print "$counter\n";

0

이것을 => -i (노드 번호의 경우) 및 -F ( '/'와 함께 디렉토리 이름 추가) 옵션과 함께 ls 사용하십시오 .

ls -ilF | egrep -v '/' | wc -l

0

A의 perl한줄 (가독성 포맷) :

perl -e 'opendir($dh, ".");
         while ( readdir($dh) ) {$count++};
         closedir $dh;
         print "$count\n";'

또는

perl -e 'opendir($dh, ".");
         @files = readdir($dh);
         closedir $dh;
         print $#files+1,"\n";'

두 번째 버전과 perl같이 grep또는 map두 번째 버전으로 배열을 수정 하는 함수를 사용할 수 있습니다 . perldoc -f readdir를 사용하는 예를 참조하십시오 grep.


0

내가 항상 사용하고 문제가 없었던 가장 간단한 버전은 다음과 같습니다. ls -b1 | wc -l


파일 이름에 \n다른 펑키 문자 가 포함되어 있으면 문제가 발생할 수 있습니다 (예 : 특정 유니스에서 허용).
— rahmu

1
답변을 게시하기 전에 명시 적으로 시도했지만 아무런 문제가 없었습니다. 노틸러스 파일 관리자를 사용하여 \ n을 포함하도록 파일 이름을 바꾸어 시도했습니다.
— 피터

당신은 그렇습니다. 그렇게 작동하지 않습니다. 나는 이것을 처음 테스트했을 때 내가 한 일을 모른다. 다시 시도하고 내 대답을 업데이트했습니다.
— 피터

아니요, 명령은 정상이지만 이미 유사한 솔루션이 있으며 숨겨진 파일은 계산되지 않습니다.
— xhienne

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.