확장자로 디렉토리의 파일 수


15

테스트 목적으로, 각 이미지 파일 유형을 파일 확장자 (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주기를 사용해야 합니까?

답변:


14

가능한 단어 분리 문제를 피하면서 다른 접근법을 제안합니다. 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[@]}$#"$@"


23

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

  1. 디렉토리의 모든 파일을 나열하십시오.
  2. 그들의 확장을 추출
  3. 결과 정렬
  4. 각 확장의 발생 횟수 계산

이런 종류의 (마지막 awk호출은 순전히 형식화를위한 것입니다) :

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

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


mhmh ... 나중에 찾은 각 확장을 필터링하여 조치를 수행해야합니까?
watchmansky

결국 당신이하고 싶은 일에 달려 있습니다. 더 많은 정보를 줄 수 있습니까?
groxxda

내 목표 : 입력 사용자 데이터에서 크기를 변경하는 각 확장 파일 (이미지 파일 만)을 처리하는 스크립트. 그래서 몇 개의 jpg 파일이 있는지, 다음 png 등에서 시작합니다.
watchmansky

스틸 드라이버 솔루션이 더 적합 할 수 있습니다.
groxxda

2
나는 파일 JPGjpg파일 을 모두 가지고 있었고 재귀 적으로 원했기 때문에 내 솔루션은 다음과 같이 작성되었습니다.find . -type f | awk -F . '{print tolower($NF)}' | sort | uniq -c | awk '{print $2,":",$1}'
Kristian

11

이것은 재귀 적으로 파일을 순회하고 다음과 일치하는 확장자를 계산합니다.

$ 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

6
find -type f | sed -e 's/.*\.//' | sort | uniq -c

3
로 시작하는 디렉토리를 잊지 마십시오 find. 또한 솔루션에 대한 간단한 설명을 제공하면 (약간의 경우에 따라 솔루션을 수정하려는 경우)이 답변을 읽는 독자에게 도움이 될 수 있습니다.
Jeff Schaller

이 솔루션은 공백이 포함 된 경로 이름을 얼마나 잘 처리합니까? 줄 바꿈?
dhag

1
find기본값은 현재 디렉토리입니다.이 방법을 사용합니다. 나는 하나님이 파일 이름에 공백이 있다고 생각하지는 않지만 그 경우에는 잘 작동합니다. 줄 바꿈이 있으면 얻을 수있는 모든 것이 필요합니다. 나는 설명에 대해 생각했지만 대답이 너무 길어질 것이라고 결정했습니다. 단순성이 중요하다고 생각합니다. 1 %의 시간에서 99 %의 사례. 이것은 아마도 버전 7과 호환됩니다.
Neik

3

어쩌면 더 짧아 질 수 있습니다

exts=( *.jpg *.png *.gif ); printf "There are ${#exts[@]}" extensions;

3

관련 뭐든지 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.


0

이 간단한 IMO에 ls를 사용할 수 있습니다.

ls -l /opt/ssl/certs/*.pem | wc -l

또는

count=$(ls -l /some/folder/*.jpg | wc -l)

또는

ls *.{mp3,exe,mp4} 2>/dev/null | wc -l

-2

확장이 확실하면 다음과 find같이 갈 수 있습니다.

find *.jpeg | wc -l

누군가가 생성 touch $'foo\nbar.jpeg하고 한 번이 아니라 두 번 계산 될 때까지 . 더 나쁜 것은, 누군가mkdir directory.jpeg; touch directory.jpeg/{1..100}.txt
Jeff Schaller
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.