Linuxマシンで、フォルダー階層をトラバースして、その中のすべての個別のファイル拡張子のリストを取得したいと思います。
シェルからこれを達成するための最良の方法は何でしょうか?
Linuxマシンで、フォルダー階層をトラバースして、その中のすべての個別のファイル拡張子のリストを取得したいと思います。
シェルからこれを達成するための最良の方法は何でしょうか?
これを試してください(それが最善の方法かどうかはわかりませんが、機能します):
find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u
次のように機能します。
パイプの必要はありませんsort
、awkはそれをすべて行うことができます:
find . -type f | awk -F. '!a[$NF]++{print $NF}'
再帰バージョン:
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
私はこれをこのフォーラムの投稿に基づいています、クレジットはそこに行くべきです。
私の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
パワーシェル:
dir -recurse | select-object extension -unique
http://kevin-berridge.blogspot.com/2007/11/windows-powershell.htmlに感謝します
ドットですべてを検索し、接尾辞のみを表示します。
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
自分のバリエーションをミックスに追加します。私はそれがロットの中で最も単純であり、効率が大きな問題ではないときに役立つと思います。
find . -type f | grep -oE '\.(\w+)$' | sort -u
私はここでたくさんの答えを試しましたが、「最良の」答えも試しました。それらはすべて、私が具体的に求めていたものには及ばなかった。したがって、過去12時間に複数のプログラムの正規表現コードを使用し、これらの回答を読んでテストしたことに加えて、これが私が思いついたものであり、まさに私が望むように機能します。
find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort -u
ファイル拡張子の数が必要な場合は、以下のコードを使用してください
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文字のファイル拡張子のグリップ」と書かれていました(必要に応じて数字を調整するだけです)。これにより、キャッシュファイルとシステムファイルを回避できます(システムファイルビットはjailを検索するためのものです)。 「」
アイデア:次の方法で特定の長さのファイル拡張子を見つけるために使用できます。
find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{4,}" | awk '{print tolower($0)}' | sort -u
ここで、4は含めるファイル拡張子の長さであり、その長さを超える拡張子も検索します。
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)
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)"
これまでのところ、改行を含むファイル名を適切に処理する応答はありません(これを入力しているときに入力された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
最もシンプルでわかりやすい方法は
for f in *.*; do echo "${f##*.}"; done | sort -u
ChristopheDの3番目の方法で変更されています。
これはまだ言及されていないと思います:
find . -type f -exec sh -c 'echo "${0##*.}"' {} \; | sort | uniq -c
別の方法:
find . -type f -name "*.*" -printf "%f\n" | while IFS= read -r; do echo "${REPLY##*.}"; done | sort -u
ドロップすることもできますが-name "*.*"
、これにより、ある種の拡張子を持つファイルのみを処理することが保証されます。
これ-printf
はfind
、bashではなく印刷物です。-printf "%f\n"
ファイル名のみを出力し、パスを削除します(そして改行を追加します)。
次に、文字列置換を使用して、。を使用して最後のドットまでを削除し${REPLY##*.}
ます。
$REPLY
これは単にread
の組み込み変数であることに注意してください。次の形式で独自のものを使用することもできwhile IFS= read -r file
ます。ここでは、$fileが変数になります。
受け入れられた答えはREGEXを使用しており、REGEXでエイリアスコマンドを作成することはできません。シェルスクリプトに入れる必要があります。私はAmazon Linux 2を使用しており、次のことを行いました。
受け入れられた回答コードを使用してファイルに入れました:
sudo vim find.sh
このコードを追加します:
find ./ -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u
次のように入力してファイルを保存します。 :wq!
sudo vim ~/.bash_profile
alias getext=". /path/to/your/find.sh"
:wq!
. ~/.bash_profile
あなたもこれを行うことができます
find . -type f -name "*.php" -exec PATHTOAPP {} +
シンプルで速いと思いました...
# 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