폴더 계층 구조에서 고유 한 파일 확장자를 모두 찾으려면 어떻게해야합니까?


235

Linux 컴퓨터에서 폴더 계층 구조를 탐색하고 그 안에있는 모든 고유 파일 확장자 목록을 얻고 싶습니다.

쉘에서 이것을 달성하는 가장 좋은 방법은 무엇입니까?

답변:


347

이것을 시도하십시오 (최상의 방법인지 확실하지 않지만 작동합니다).

find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u

다음과 같이 작동합니다.

  • 현재 폴더에서 모든 파일 찾기
  • 파일 확장명을 인쇄합니다 (있는 경우)
  • 고유 한 정렬 된 목록 만들기

8
단지 참조 : 당신은 (예를 들어, 검색에서 일부 디렉토리를 제외 할 경우 .svn), 사용 find . -type f -path '*/.svn*' -prune -o -print | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u 소스
데니스 Golomazov을

공백은 차이가 없습니다. 각 파일 이름은 별도의 줄에 있으므로 파일 목록 구분 기호는 공백이 아닌 "\ n"입니다.
Ivan Nevostruev

1
Windows에서는이 방법이 작동하는 것보다 훨씬 빠르며 찾기보다 훨씬 빠릅니다. dir / s / b | perl -ne 'm /\.([^^.\\\\]+)$/ 인 경우 $ 1 인쇄 |'| 종류 -u
Ryan Shillington


8
변형은 다음과 같습니다. 확장자 당 개수가 포함 된 목록이 표시됩니다.find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort | uniq -c | sort -n
marcovtwout

55

파이프가 필요 sort하지 않습니다. awk는 모든 것을 할 수 있습니다.

find . -type f | awk -F. '!a[$NF]++{print $NF}'

나는 이것을 별칭으로 작동시키지 않고, awk를 얻고있다 : 소스 라인 1 컨텍스트의 구문 오류는 >>>! a [] <<< awk : 소스 라인 1에서 bailing out. 내가 뭘 잘못하고 있니? 내 별칭은 다음과 같이 정의됩니다 : alias file_ext = "find. -type f -name ' . '| awk -F. '! a [$ NF] ++ {print $ NF}'"
user2602152

2
@ user2602152 문제는 전체 one-liner를 alias명령에 대한 따옴표로 묶으려고 하지만 명령 자체가 이미 find 명령에서 따옴표를 사용한다는 것입니다. 이 문제를 해결하기 위해 다음 bash과 같이 리터럴 문자열 구문을 사용합니다.alias file_ext=$'find . -type f -name "*.*" | awk -F. \'!a[$NF]++{print $NF}\''
SiegeX

하나의 하위 디렉토리에가 있으면 작동하지 않습니다. 파일 이름에 파일 확장자가 없습니다. 예 : maindir에서 실행할 때 실패합니다maindir/test.dir/myfile
Nelson Teixeira

1
@NelsonTeixeira -printf "%f\n"'find'명령 끝에 추가 하고 테스트를 다시 실행하십시오.
SiegeX

41

재귀 버전 :

find . -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u

총계를 원할 경우 (확장자가 몇 번이나 보 였는지) :

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

비 재귀 (단일 폴더) :

for f in *.*; do printf "%s\n" "${f##*.}"; done | sort -u

나는 이 포럼 게시물을 기반으로 , 신용은 거기에 가야합니다.


큰! 또한 내 자식 시나리오에서 작동하며 마지막 커밋에서 어떤 유형의 파일을 만졌는지 알아 내려고했습니다.git show --name-only --pretty="" | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u
vulcan raven

30

파워 쉘 :

dir -recurse | select-object extension -unique

http://kevin-berridge.blogspot.com/2007/11/windows-powershell.html 덕분에


20
OP는 "리눅스 머신에서"라고 말했다
Forbesmyester

9
실제로 리눅스를위한 prowershell이 ​​있습니다 : github.com/Microsoft/PowerShell-DSC-for-Linux
KIC

4
작성된 것처럼, 이것도 디렉토리가있는 디렉토리를 선택 .합니다 (예 : 출력 jquery-1.3.4과 같이 .4표시됨). dir -file -recurse | select-object extension -unique파일 확장자 만 얻으려면로 변경하십시오 .
mcw

1
@Forbesmyester : 나 같은 Windows 사용자는이 질문을 찾을 수 있습니다. 따라서 이것은 유용합니다.
Roel

1
Powershell의 답변에 감사드립니다. 사용자가 검색하는 방식을 가정하지 않습니다. 많은 사람들이 이유를 위해 찬성했습니다
Mahesh

20

나의 awk-less, sed-less, Perl-less, Python-less POSIX 호환 대안 :

find . -type f | rev | cut -d. -f1 | rev  | tr '[:upper:]' '[:lower:]' | sort | uniq --count | sort -rn

요령은 선을 뒤집고 처음에 확장을 자르는 것입니다.
또한 확장명을 소문자로 변환합니다.

출력 예 :

   3689 jpg
   1036 png
    610 mp4
     90 webm
     90 mkv
     57 mov
     12 avi
     10 txt
      3 zip
      2 ogv
      1 xcf
      1 trashinfo
      1 sh
      1 m4v
      1 jpeg
      1 ini
      1 gqv
      1 gcs
      1 dv

mac에서는 uniqfull 플래그 --count가 없지만 제대로 -c작동합니다
worc

12

점이있는 모든 것을 찾고 접미사 만 표시하십시오.

find . -type f -name "*.*" | awk -F. '{print $NF}' | sort -u

모든 접미사에 3자가 있다는 것을 알고 있다면

find . -type f -name "*.???" | awk -F. '{print $NF}' | sort -u

또는 sed는 1 ~ 4 자의 모든 접미사를 표시합니다. {1,4}를 접미사에서 예상되는 문자 범위로 변경하십시오.

find . -type f | sed -n 's/.*\.\(.\{1,4\}\)$/\1/p'| sort -u

1
파이프가 '정렬'할 필요가 없습니다. awk는 모든 것을 할 수 있습니다 : find. -type f -name " . "| awk -F. '! a [$ NF] ++ {print $ NF}'
SiegeX 2009

@SiegeX Yours는 별도의 답변이어야합니다. 확장명을 찾은대로 인쇄하므로 큰 폴더에 가장 적합한 명령을 찾았습니다. 그러나 다음과 같아야합니다. -name " . "
Ralf

@Ralf 완료, 여기 에 답변을 게시 했습니다 . -name "."그것이 이미 무엇인지에 대한 것의 의미에 대해 잘 모르겠습니다
SiegeX

나는 그것이 -name "*. *"이어야한다는 것을 의미했지만, StackOverflow는 주석에서 * 문자를 제거합니다.
Ralf

이것은 대답으로 받아 들여야 할 것 같습니다. awk는 명령 줄 도구로 perl보다 바람직하며 작은 상호 운용 가능한 프로그램을 응집력 있고 읽기 쉬운 절차로 만드는 유닉스 철학을 포함합니다.
Jon z

7

믹스에 내 변형을 추가합니다. 나는 그것이 가장 단순하고 효율성이 큰 관심사가 아닐 때 유용 할 수 있다고 생각합니다.

find . -type f | grep -o -E '\.[^\.]+$' | sort -u

1
정규식은 단일 문자로 구성된 확장명과 만 일치하므로 상당히 제한적이지만 이식성이 +1입니다. 허용 된 답변에서 정규식을 사용하는 것이 더 좋습니다.$ find . -type f | grep -o -E '\.[^.\/]+$' | sort -u
mMontu

1
동의했다. 나는 거기서 조금 느슨해졌다. 발견 한 실수를 해결하기 위해 내 답변을 편집합니다.
gkb0986

멋있는. 따옴표를 큰 따옴표로 묶고, grep biraries 및 종속성을 업데이트합니다 (git와 함께 제공되는 것이 오래 되었기 때문에). 이제 Windows에서 작동합니다. 리눅스 사용자처럼 느껴집니다.
msangel

5

파이썬에서는 공백 확장을 포함하여 매우 큰 디렉토리에 생성기를 사용하고 각 확장이 표시되는 횟수를 얻습니다.

import json
import collections
import itertools
import os

root = '/home/andres'
files = itertools.chain.from_iterable((
    files for _,_,files in os.walk(root)
    ))
counter = collections.Counter(
    (os.path.splitext(file_)[1] for file_ in files)
)
print json.dumps(counter, indent=2)

5

나는 여기에 많은 답변을 시도했다. 심지어 "최고의"답변까지. 그들은 모두 내가 구체적으로 추구했던 것보다 부족했습니다. 그래서 지난 12 시간 동안 여러 프로그램에 대한 정규식 코드에 앉아 이러한 답변을 읽고 테스트하는 것 외에도 이것이 내가 원하는 것처럼 정확하게 작동했습니다.

 find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort -u
  • 확장자가있는 모든 파일을 찾습니다.
  • 확장 만 그립
  • 2 ~ 16 자 사이의 파일 확장자를 잡으십시오 (필요에 맞지 않으면 숫자를 조정하십시오). 캐시 파일 및 시스템 파일을 피할 수 있습니다 (시스템 파일 비트는 감옥을 검색하는 것임).
  • 확장 프로그램을 소문자로 인쇄하십시오.
  • 고유 한 값만 정렬하고 가져옵니다. 원래 나는 awk 답변을 시도했지만 대소 문자 구분이 다양한 두 번 인쇄 된 항목입니다.

파일 확장자가 필요한 경우 아래 코드를 사용하십시오.

find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort | uniq -c | sort -rn

이러한 방법을 완료하는 데 시간이 걸리고 문제를 해결하는 가장 좋은 방법은 아니지만 작동합니다.

업데이트 : @ alpha_989 당 긴 파일 확장자는 문제를 일으킬 것입니다. 원래 정규식 "[[: alpha :]] {3,6}"때문입니다. 정규식 "[[: alpha :]] {2,16}"을 포함하도록 답변을 업데이트했습니다. 그러나이 코드를 사용하는 사람은 해당 숫자가 확장이 최종 출력에 허용되는 시간의 최소값과 최대 값이라는 것을 알고 있어야합니다. 이 범위를 벗어나는 것은 출력에서 ​​여러 줄로 나뉩니다.

참고 : 원래 게시물은 "-3 ~ 6 자 사이의 파일 확장자에 대한 Greps (필요에 맞지 않으면 숫자를 조정하십시오)를 읽었습니다. 이는 캐시 파일 및 시스템 파일을 피하는 데 도움이됩니다 (시스템 파일 비트는 감옥을 찾는 것입니다). "

아이디어 : 다음을 통해 특정 길이의 파일 확장자를 찾는 데 사용할 수 있습니다.

 find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{4,}" | awk '{print tolower($0)}' | sort -u

여기서 4는 포함 할 파일 확장자 길이이며 해당 길이 이상의 확장자를 찾습니다.


카운트 버전은 재귀입니까?
페르난도 몬토야

@ 신라이, 일반적으로 잘 작동합니다. 그러나 .download와 같이 정말 긴 임의의 파일 확장자가있는 경우 ".download"를 2 개의 부분으로 나누고 "downlo"인 파일 2 개와 "ad"인 파일 2 개를보고합니다.
alpha_989

@ alpha_989, 정규 표현식 "[[: alpha :]] {3,6}"때문에 3 자 미만의 확장명에 문제가 발생합니다. 필요한 것에 맞게 조정하십시오. 개인적으로 대부분의 경우 2,16이 작동한다고 말하고 싶습니다.
Shinrai

답장을 보내 주셔서 감사합니다 .. 네 .. 나중에 깨달았습니다. 내가 언급 한 것과 비슷하게 수정 한 후에 잘 작동했습니다.
alpha_989

3

Perl을 사용하는 다른 솔루션이 이미 있으므로 :

파이썬을 설치했다면 쉘에서 할 수도 있습니다.

python -c "import os;e=set();[[e.add(os.path.splitext(f)[-1]) for f in fn]for _,_,fn in os.walk('/home')];print '\n'.join(e)"

2

지금까지 답글은 개행 문자가있는 파일 이름을 올바르게 처리하지 못했습니다 (ChristopheD는 제외하고 입력했습니다). 다음은 쉘 한 줄짜리가 아니지만 작동하며 합리적으로 빠릅니다.

import os, sys

def names(roots):
    for root in roots:
        for a, b, basenames in os.walk(root):
            for basename in basenames:
                yield basename

sufs = set(os.path.splitext(x)[1] for x in names(sys.argv[1:]))
for suf in sufs:
    if suf:
        print suf

2

나는 이것이 아직 언급되지 않았다고 생각한다.

find . -type f -exec sh -c 'echo "${0##*.}"' {} \; | sort | uniq -c

각 파일마다 새로운 프로세스를 생성하기 때문에 속도가 느려질 수 있습니다.
Ondra Žižka

1

가장 간단하고 간단한 방법은

for f in *.*; do echo "${f##*.}"; done | sort -u

ChristopheD의 세 번째 방법으로 수정되었습니다.


0

당신은 또한 이것을 할 수 있습니다

find . -type f -name "*.php" -exec PATHTOAPP {} +

0

나는 그것을 간단하고 빠르게 발견했습니다 ...

   # find . -type f -exec basename {} \; | awk -F"." '{print $NF}' > /tmp/outfile.txt
   # cat /tmp/outfile.txt | sort | uniq -c| sort -n > tmp/outfile_sorted.txt

0

허용 된 답변은 REGEX를 사용하며 REGEX로 별칭 명령을 만들 수 없으며 쉘 스크립트에 넣어야합니다 .Amazon Linux 2를 사용하고 있으며 다음을 수행했습니다.

  1. 다음을 사용하여 허용되는 응답 코드를 파일에 넣습니다.

    sudo vim find.sh

이 코드를 추가하십시오 :

find ./ -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u

다음을 입력하여 파일을 저장하십시오. :wq!

  1. sudo vim ~/.bash_profile

  2. alias getext=". /path/to/your/find.sh"

  3. :wq!

  4. . ~/.bash_profile

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