디렉토리 브랜치 내에서 특정 파일의 총 크기 찾기


140

이미지 저장소 디렉토리가 있다고 가정하자. 여기 ./photos/john_doe에는 여러 개의 특정 디렉토리가있는 여러 개의 서브 디렉토리가있다 (예 :) *.jpg. john_doe지점 아래에서 해당 파일의 요약 크기를 어떻게 계산할 수 있습니까?

나는 시도 du -hs ./photos/john_doe/*/*.jpg했지만 이것은 개별 파일 만 보여줍니다. 또한 john_doe디렉토리 의 첫 번째 중첩 수준 만 추적 john_doe/june/하지만 건너 뜁니다 john_doe/june/outrageous/.

그렇다면 어떻게 전체 파일을 가로 질러 특정 파일의 크기를 합산 할 수 있습니까?

답변:


183
find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$

du파일 목록이 매우 길어서 두 번 이상의 호출 이 필요한 경우 여러 개의 총계가보고되며 합산되어야합니다.


7
-iname 'file *'찾기 -exec du -cb {} + | grep total $ | 컷 -f1 | 페이스트 -sd +-| bc # 합계 바이트 크기
Michal Čizmazia

3
시스템이 다른 언어로 작동하는 경우 폴란드어에서 total $를 razem $와 같은 다른 단어로 변경해야합니다.
Zbyszek

1
다음 LC_ALL=POSIX과 같이 항상 grep을 접두어로 추가 할 수 있습니다 .LC_ALL=POSIX find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$
Sven

2
를 사용하지 않는 경우 -namegrep을로 변경 grep -P "\ttotal$"하거나 그렇지 않으면 "total"로 끝나는 모든 파일을 캡처합니다.
thdoan

3
@ MichalČizmazia 일부 쉘 (예 : Windows 용 Git Bash)은와 함께 제공되지 bc않으므로 다음과 같은보다 편리한 솔루션이 있습니다.find -name '*.jpg' -type f -exec du -bc {} + | grep total$ | cut -f1 | awk '{ total += $1 }; END { print total }'
thdoan

50
du -ch public_html/images/*.jpg | grep total
20M total

.jpg이 디렉토리에있는 파일 의 전체 사용량을 알려줍니다 .

여러 디렉토리를 다루려면 아마도 이것을 find어떻게 든 결합해야 할 것입니다 .

당신을 인정한 뒤 명령 예 유용을 (그것도 포함 find)


2
이것은 기본 디렉토리를 통과하지 않습니까?
mbaitoff 2016 년

이것은 허용되는 솔루션보다 입력하기가 쉽지만 절반에 불과하며 하위 디렉토리에 이미지가 포함되지 않습니다. 모든 파일이 하나의 디렉토리에 있는지 아는 것이 좋습니다.
gbmhunter

@gbmhunter -ch에 -R 매개 변수를 추가하면 디렉토리 트리를 재귀 적으로 탐색 할 때 서브 디렉토리도 얻을 수 있다고 생각합니다. 현재 컴퓨터를 사용하여 확인을 시도하고 있지 않습니다.
레본

1
나는 보이지 않는 -R에서 옵션 man7.org/linux/man-pages/man1/du.1.html을 . 그리고 쉘이 인수를 전달하기 전에 glob 확장을 수행하기 때문에이 경우 재귀 옵션이 도움이되지 않는다고 생각합니다 du.
gbmhunter

22

주로 두 가지가 필요합니다.

  • -c옵션을 사용하는 du, 총합계를 생산하도록 지시합니다;
  • **( 활성화 지침 ) 또는 find( ) 또는 하위 디렉토리를 통과하기.
du -ch -- **/*.jpg | tail -n 1

아주 좋은 답변입니다. 찾기를 사용하는 것보다 간단한 (한 * 또는 ** 디렉토리 구조와 일치)
앙드레 드 미란다

또한 매우 긴 파일 목록을 처리 할 수 ​​있지만 사용 find하면 잘못된 결과가 반환 될 수 있습니다.
Eric Fournie

bash 괄호 확장을 사용하면 여러 세트의 와일드 카드도 측정 할 수 있습니다. du -ch -- ./{dir1,dir2}/*.jpg또는du -ch -- ./{prefix1*,prefix2*}.jpg
J.Money

@EricFournie 그러나 Argument list too long약 300k 텍스트 파일을 처리 할 때 오류 가 발생했습니다.
xtluo

명령에 대한 최대 인수 수 (이 경우 와일드 카드 확장에서 반환 된 파일 이름)는로 확인할 수 있습니다 getconf ARG_MAX. 더 많은 것이 있으면 파일을 하나씩 처리하거나 for 루프를 사용하여 일괄 처리해야합니다.
에릭 푸니

17

궁극적 인 답변은 다음과 같습니다.

{ find <DIR> -type f -name "*.<EXT>" -printf "%s+"; echo 0; } | bc

그리고 더 빠른 버전, RAM에 의해 제한되지 않지만 bignum을 지원하는 GNU AWK가 필요합니다.

find <DIR> -type f -name "*.<EXT>" -printf "%s\n" | gawk -M '{t+=$1}END{print t}'

이 버전에는 다음과 같은 기능이 있습니다.

  • find찾고있는 파일을 지정하는 모든 기능
  • 수백만 개의 파일 지원
    • 다른 답변은 인수 목록의 최대 길이에 의해 제한됩니다
  • 최소 파이프 처리량으로 3 개의 간단한 프로세스 만 생성
    • 여기에 많은 답변이 C + N 프로세스를 생성합니다. 여기서 C는 일정하고 N은 파일 수입니다.
  • 문자열 조작을 방해하지 않습니다
    • 이 버전은 grepping이나 regexing을 수행하지 않습니다.
    • 글쎄, find파일 이름의 간단한 와일드 카드 일치를 수행합니다
  • 선택적으로 읽을 수있는 형식으로 합계 포맷 (예를. 5.5K, 176.7M...)
    • 그 추가 할 | numfmt --to=si

여는 중괄호 다음과 닫는 중괄호 앞에 공백을 도입했을 때만 효과가 있었지만이 대답의 단순함이 마음에 듭니다. 그것이 실제로 'infiinte'파일 수를 지원하는지 궁금합니다. :)
andyb

1
@andyb 의견을 보내 주셔서 감사합니다. 중괄호 주위의 공백은 실제로 BASH에 필요합니다 .ZSH를 사용하고 있으므로 그 사실을 알지 못했습니다. bc의 메모리 사용량이 증가함에 따라 bc의 메모리 사용량이 느리게 증가함에 따라 파일 수는 시스템에서 사용 가능한 RAM에 의해 제한됩니다.
Jan Chren-rindeal

8

지금까지 주어진 대답은 find에서 du로 전달 된 파일 목록이 너무 길어서 find가 목록을 청크로 자동 분할하여 여러 번 발생하는 것을 고려하지 않습니다 total.

당신도 grep total(! 로케일) 수동 요약, 또는 다른 명령을 사용합니다. AFAIK는 find로 찾은 모든 파일의 총계 (킬로바이트)를 얻는 방법은 두 가지뿐입니다.
find . -type f -iname '*.jpg' -print0 | xargs -r0 du -a| awk '{sum+=$1} END {print sum}'

설명
find . -type f -iname '*.jpg' -print0: 대소 문자에 관계없이 확장자가 jpg 인 모든 파일 (예 : * .jpg, * .JPG, * .Jpg ...)을 찾아 출력합니다 (널 (NULL)로 종료).
xargs -r0 du -a: -r : Xargs는 인수가 전달되지 않아도 명령을 호출하여 -r을 방지합니다. -0은 널 종료 문자열을 의미합니다 (줄 바꿈이 종료되지 않음).
awk '{sum+=$1} END {print sum}': 이전 명령으로 출력 된 파일 크기를 합산

그리고 참고로, 다른 방법은
find . -type f -iname '*.jpg' -print0 | du -c --files0-from=-


추가 힌트 : 23428 파일 (이미지 인 22323)이있는 HDD에서 첫 번째 방법은 1 초 동안 실행되고 두 번째 방법은 3.8 초 동안 실행됩니다.
Jan

둘 다 GNU 시스템을 가정합니다. 첫 번째는 파일 이름에 줄 바꿈 문자가 포함되어 있지 않다고 가정합니다.
Stéphane Chazelas

du --file0-from당신이 그것을 먼저 실행했기 때문에 더 오래 걸렸을 것입니다 (캐싱 효과).
Stéphane Chazelas

을 사용 xargs하면 여러 개가 du -a실행될 수 있으므로 하드 링크가 있으면 불일치가 발생할 수 있습니다.
Stéphane Chazelas

3

파일 목록이 너무 커서 du -cGNU 시스템에서 단일 호출로 전달할 수없는 경우 다음을 수행 할 수 있습니다.

find . -iname '*.jpg' -type f -printf '%b\t%D:%i\n' |
  sort -u | cut -f1 | paste -sd+ - | bc

(크기는 512 바이트 블록 수로 표시됨). 마찬가지로 du한 번만 하드 링크를 계산하려고합니다. 하드 링크에 신경 쓰지 않으면 다음과 같이 단순화 할 수 있습니다.

(printf 0; find . -iname '*.jpg' -type f -printf +%b) | bc

당신이 크기 대신 디스크 사용을 원하는 경우, 교체 %b와 함께 %s. 그러면 크기가 바이트로 표시됩니다.


-bash: bc: command not foundCentos-Linux 2.6.32-431.el6.x86_64
yeya

@yeya, CentOS 배포가 중단 된 것 같습니다. bc선택적 POSIX 명령입니다.
Stéphane Chazelas

1

지금까지 언급 한 솔루션은 비효율적이며 (exec가 비싸다) 파일 목록이 길거나 Mac OS X에서 작동하지 않는 경우 합산하려면 추가 수동 작업이 필요합니다. 다음 솔루션은 매우 빠르며 모든 시스템에서 작동해야합니다. 총 답변을 GB 단위로 표시합니다 (총 MB를 보려면 / 1024 제거). find . -iname "*.jpg" -ls |perl -lane '$t += $F[6]; print $t/1024/1024/1024 . " GB"'


어느 쪽 -iname-ls휴대용 / 표준 없습니다, 그래서하지 않습니다 모든 시스템에서 작동 중 하나. 줄 바꿈 문자가 포함 된 파일 이름 또는 symlink 대상이있는 경우에도 제대로 작동하지 않습니다.
Stéphane Chazelas

또한 디스크 사용량이 아니라 파일 크기의 합계를 나타냅니다. 심볼릭 링크의 경우 심볼릭 링크가 가리키는 파일이 아닌 심볼릭 링크의 크기를 제공합니다.
Stéphane Chazelas

1

Zbyszek이 이미 그의 의견에서 지적했듯이 SHW의 어떤 로케일에서도 작동하도록 큰 대답을 향상시킵니다.

LC_ALL=C find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$

1

du는 자연스럽게 디렉토리 계층을 순회하며 awk는 필터링을 수행 할 수 있으므로 다음과 같이 충분할 수 있습니다.

du -ak | awk 'BEGIN {sum=0} /\.jpg$/ {sum+=$1} END {print sum}'

이것은 GNU없이 작동합니다.


1
stat검색된 패턴과 일치하지 않는 파일을 호출하기 때문에 비용이 더 많이 듭니다 .
법률 29

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