확장명으로 디렉토리의 파일 수 계산

확장명으로 디렉토리의 파일 수 계산

테스트 목적으로 각 이미지 파일 형식을 파일 확장자(jpg="yes")로 구분하여 디렉터리에 있는 이미지 파일 수를 계산하고 싶습니다. 이는 나중에 각 파일 확장자에 대해 작업을 수행하는 다른 스크립트에 유용할 것이기 때문입니다. JPEG 파일에만 다음과 같은 것을 사용할 수 있습니까?

jpg=""
count=`ls -1 *.jpg 2>/dev/null | wc -l`
if [ $count != 0 ]
then
echo jpg files found: $count ; jpg="yes"
fi

파일 확장자 jpg, png, bmp, raw 등을 고려하여 while이 작업을 수행하려면 루프를 사용해야 합니까?

답변1

내 접근 방식은 다음과 같습니다

  1. 디렉토리의 모든 파일 나열
  2. 확장자를 추출하세요
  3. 결과 정렬
  4. 각 확장자의 발생 횟수를 계산합니다.

다음과 같습니다(마지막 awk호출은 순전히 서식 지정을 위한 것입니다).

ls -q -U | awk -F . '{print $NF}' | sort | uniq -c | awk '{print $2,$1}'

ls-U( 최적화를 위해 여기에서 정렬을 건너뛰는 GNU 옵션이 있다고 가정합니다 . 지원되지 않는 경우 기능에 영향을 주지 않고 안전하게 제거할 수 있습니다.)

답변2

이는 파일을 반복적으로 반복하고 일치하는 확장자를 계산합니다.

$ find . -type f | sed -e 's/.*\.//' | sort | uniq -c | sort -n | grep -Ei '(tiff|bmp|jpeg|jpg|png|gif)$'
   6 tiff
   7 bmp
  26 jpeg
  38 gif
  51 jpg
  54 png

답변3

가능한 단어 분할 문제를 피하기 위해 다른 접근 방식을 제안하고 싶습니다.ls

#!/bin/bash

shopt -s nullglob

for ext in jpg png gif; do 
  files=( *."$ext" )
  printf 'number of %s files: %d\n' "$ext" "${#files[@]}"

  # now we can loop over all the files having the current extension
  for f in "${files[@]}"; do
    # anything else you like with these files
    :
  done 

done

files특정 확장명의 각 파일에 대해 실행하려는 다른 명령을 사용하여 배열을 반복할 수 있습니다.


이식성이 더 높거나 배열을 명시적으로 제공하지 않는 쉘의 경우 쉘의 위치 인수 배열을 재사용할 수 있습니다.

set -- *."$ext"

그런 다음 ${#files[@]}교체 ${files[@]}하고$#"$@"

답변4

ls특수 문자(공백 및 기타 기호) 와 관련된 모든 항목은 예상치 못한 결과를 초래할 수 있습니다. 배열과 같은 모든 bashism은 이식 가능하지 않습니다. 관련된 모든 작업은 while read일반적으로 느립니다.

반면에 find매우 유연하고(필터링 옵션이 많음), [적어도] 두 개의 구문이 있고 특수 문자에 대해 안전하며... 큰 디렉터리에서 잘 확장됩니다.

이 예에서는 -iname대문자와 소문자 확장자를 일치시켰습니다. 또한 -maxdepth 1귀하의 질문과 관련하여 "현재 디렉토리"를 제한했습니다 . 줄 수를 세는 대신(파일 이름에 CR/LF가 포함될 수 있음) -print0각 파일 이름 끝에 NULL 바이트가 인쇄되므로 | tr -d -c "\000" | wc -l파일 수(NULL 바이트!)가 정확하게 계산됩니다.

extensions="jpg png gif"
for ext in $extensions; do
  c=$(find . -maxdepth 1 -iname "*.$ext" -print0 | tr -d -c "\000" | wc -c)
  if [ $c -gt 0 ]; then
    echo "Found $c  *.$ext files"

    find . -maxdepth 1 -iname "*.$ext" -print0 | xargs -0 -r -n1 DOSOMETHINGHERE
    # or #  find . -maxdepth 1 -iname "*.$ext" -exec "ls" "-l" "{}" ";"
  fi
done

PS는 -print0 | tr -d -c "\000" | wc -c또는로 대체될 수도 있습니다.-printf "\000" | wc -c-printf '\n' | wc -l

관련 정보