フォルダ階層内の個別のファイル拡張子をすべて見つけるにはどうすればよいですか?


235

Linuxマシンでは、フォルダー階層をたどり、その中の個別のファイル拡張子すべてのリストを取得したいと考えています。

シェルからこれを達成するための最良の方法は何でしょうか?

回答:


347

これを試してください(それが最善の方法かどうかはわかりませんが、うまくいきます):

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

次のように機能します。

  • 現在のフォルダーからすべてのファイルを検索
  • ファイルの拡張子を印刷します
  • 一意のソートリストを作成する

8
参考までに:検索から一部のディレクトリを除外する場合(例.svnfind . -type f -path '*/.svn*' -prune -o -print | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u
:)

スペースは何の違いもありません。各ファイル名は別々の行にあるため、ファイルリストの区切り文字はスペースではなく「\ n」になります。
Ivan Nevostruev 2013

1
Windowsでは、これはよりうまく機能し、findよりもはるかに高速です。perl -ne 'm /\.([^^.\\\\]+)$/の場合$ 1を出力する' | sort -u
Ryan Shillington、

3
答えのgitバリエーション:代わりに使用git ls-tree -r HEAD --name-onlyfind
jakub.g

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でエラーが発生しています。私のエイリアスは次のように定義されています:エイリアスfile_ext = "find。-type f -name ' ' | awk -F。 '!a [$ NF] ++ {print $ NF}'"
user2602152

2
@ user2602152問題は、aliasコマンドのワンライナー全体を引用符で囲むことですが、コマンド自体はすでにfindコマンドで引用符を使用しています。これを修正するために私が使用しますbash:ようさんリテラル文字列構文をalias file_ext=$'find . -type f -name "*.*" | awk -F. \'!a[$NF]++{print $NF}\''
SiegeX

1つのサブディレクトリにがある場合、これは機能しません。名前で、ファイルにはファイル拡張子がありません。例:maindirから実行すると失敗するmaindir/test.dir/myfile
Nelson Teixeira

1
@NelsonTeixeira -printf "%f\n"'find'コマンドの最後に追加して、テストを再実行します。
SiegeX 2017

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のシナリオのために働く、私は最後のコミットに触れているファイルの種類を把握しようとしたgit show --name-only --pretty="" | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u
バルカンravenが

30

パワーシェル:

dir -recurse | select-object extension -unique

http://kevin-berridge.blogspot.com/2007/11/windows-powershell.htmlに感謝


20
OPは「Linuxマシン上」
Forbesmyester

9
実際には、現在Linux用のProwershellがあります:github.com/Microsoft/PowerShell-DSC-for-Linux
KIC

4
書かれているように、これは.中にaがあるディレクトリも取得します(たとえば、出力のjquery-1.3.4よう.4に表示されます)。dir -file -recurse | select-object extension -uniqueファイル拡張子のみを取得するように変更します。
mcw 2018年

1
@Forbesmyester:(私のような)Windowsを使用している人はこの質問を見つけます。これは便利です。
Roel

1
Powershellの回答をありがとう。ユーザーの検索方法を想定していません。多くの人々が理由のために賛成した
Mahesh

20

私のawkなし、sedなし、Perlなし、Pythonなしの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上で、uniq完全な旗を持っていません--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

@SiegeXあなたのものは別の答えになるはずです。それはそれがそれらを見つけると拡張機能を印刷するので、そのコマンドは大きなフォルダーに最適に機能することがわかりました。ただし、次のようになることに注意してください
Ralf

@ラルフは完了しました、ここに回答を投稿しました-name "."それがすでにそうであるので、あなたが何を意味しているのかよくわからない
SiegeX

それは-name "*。*"である必要があることを意味しましたが、StackOverflowはおそらくコメントでも発生した*文字を削除します。
ラルフ、

これは受け入れられる答えであるように思われます。awkはコマンドラインツールとしてperlよりも望ましいものであり、小さな相互運用可能なプログラムをまとまりのある読みやすい手順にパイプするというUNIXの哲学を採用しています。
Jon z

7

自分のバリエーションをミックスに追加する。これは最も単純な方法であり、効率がそれほど重要ではない場合に役立ちます。

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

1
移植性のための+1。ただし、1文字で構成される拡張子にのみ一致するため、正規表現は非常に制限されています。受け入れられた回答からの正規表現を使用する方が良いように見えます:$ find . -type f | grep -o -E '\.[^.\/]+$' | sort -u
mMontu

1
同意した。そこで少したるんだ。あなたが見つけた間違いを修正するために私の答えを編集します。
gkb0986 2013

涼しい。引用符を二重引用符に変更し、grepのバイナリと依存関係を更新します(gitで提供されるものが古くなっているため)、現在はこの作業はWindowsで行われています。Linuxユーザーのように感じます。
msangel 2015

5

Pythonでは、空白の拡張を含む非常に大きなディレクトリにジェネレータを使用し、各拡張が表示される回数を取得します。

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。
  • 一意の値のみを並べ替えて取得します。もともと私はawkの答えを試してみましたが、大文字と小文字の区別が異なるアイテムを2倍に印刷しました。

ファイル拡張子の数が必要な場合は、以下のコードを使用してください

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文字のファイル拡張子のグレープ(必要に応じて数値を調整してください)を読んでいます。これにより、キャッシュファイルやシステムファイルを回避できます(システムファイルビットは刑務所を検索するためです)。 」

アイデア:次の方法で特定の長さのファイル拡張子を見つけるために使用できます。

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

ここで、4は含めるファイル拡張子の長さで、その長さを超える拡張子も検索します。


カウントバージョンは再帰的ですか?
Fernando Montoya、

@Shinrai、一般的にうまくいきます。しかし、.downloadなどの非常に長いランダムなファイル拡張子がある場合、「。download」が2つの部分に分割され、「downlo」である2つのファイルと「ad」である2つのファイルが報告されます
alpha_989

@ alpha_989、これは正規表現「[[:alpha:]] {3,6}」が原因で、3文字未満の拡張子の問題も発生します。必要に応じて調整してください。個人的には、ほとんどの場合2,16でうまくいくと思います。
Shinrai 2018

返信ありがとう..ええ..それは後で気づいたことです。私があなたが言ったようにそれを修正した後、それはうまくいきました。
alpha_989 2018

3

Perlを使用する別のソリューションがすでにあるので:

Pythonがインストールされている場合は、(シェルから)次のようにすることもできます。

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žka19年

1

最もシンプルで簡単な方法は

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

ChristopheDの3番目の方法で変更されています。


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を使用してエイリアスコマンドを作成することはできません。これをシェルスクリプトに挿入する必要があります。AmazonLinux 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.