再帰的にファイルのリストを取得するには?

再帰的にファイルのリストを取得するには?

次の形式で出力したいと思います。

/media/username/New/Audio/time machine by Ariya Hedie.mp3
/media/username/New/Audio/You areever alone by Dj Quads.flac
/media/username/New/Audio/You'rehe Boss by The Barr Brothers.opus
/media/username/New/Audio/Your Wedding byosimo Fogg.mp3
/media/username/New/Audio/You,y Love by Floppyircus.opus
/media/username/New/Library/Yup byteven O'Brien.flac
/media/username/New/Library/Zen by Warptech.opus
/media/username/New/Library/無機質な怒りに対する優しさの反論.opus
/media/username/New/Library/鎖 -hain Border byaoyaakamata.opus

ファイルはopus、mp3など、さまざまな形式の音楽ファイルです。フォルダには音楽以外のファイルは含まれていません。ファイル名にはUnicode文字が含まれることがよくあります。

ベストアンサー1

.lua名前がディレクトリ内または下に終わる通常のファイルへのフルパスが必要な場合は/media/username標準ですfind

LC_ALL=C find /media/username -name '*.lua' -type f

リストをアルファベット順に並べ替えるためにパイプすることができますが、sortこれはファイルパスに改行文字が含まれていない特殊な場合にのみ機能し、複数行のファイルパスに散在する行が発生する可能性があります。たとえば、

/media/username/my
dir/my
strange file.lua

にパイプされると、sort次のようになります(ほとんどのロケールで)。

dir/my
/media/username/my
strange file.lua

複数行のパスを壊さずにこれらのパスを並べ替えるには、次のようにします。

LC_ALL=C find /media/username -name '*.lua' -type f -print0 |
  sort -z |
  tr '\0' '\n'

これにはGNU拡張が必要な​​ので、もはや標準ではありませんfindsort

あるいは、bashの代わりにzshシェルを使用することもできます。 globはすべてのシェルのようにデフォルトで語彙的にソートされていますが、ファイルタイプによるフィルタリング(ここの例.と同じ修飾子を使用)も受け入れ、再帰的Globbingをサポートします。-type f

print -rC1 /media/username/**/*.lua(ND.)

他の選択肢は次のfindとおりです。rawhideCに似たクエリ言語を使用してください。

LC_ALL=C rh -e '"*.lua" && file' /media/username

またはfd-findfdfind、時にはいくつかのシステムで利用可能です。

fdfind -usgtf '*.lua' /media/username

不足:

fdfind --unrestricted --case-sensitive --glob --type file '*.lua' /media/username

(/fdfindもありますが/フラグを無視しているようで、一般的に自分が望むものが何であるか、自分よりもよく知っていると思う厄介な傾向があります。)-e--extension-s--case-sensitive

fdfindリストの並べ替えの基本的なサポートはありませんが、rh同じトリックを使用してNUL区切りリスト(両方ともオプションを含む)を印刷し、必要に応じて-0NULsort -zを改行区切りtrリストにパイプすることができます。

この*.luaパターンは、シェルグローブで使用されているパターンと同じです。*任意の数の文字と一致します。文字を形成するかどうかにかかわらず、すべてのバイトシーケンスを一致させるために、一部のツールや一部のシステムまたはバージョンでは、環境を find コマンドに渡してCロケールを設定します。LC_ALL=C

名前に関係なく一般ファイルを検索するには、次のようにします。

  • -name '*.lua'次に削除find(もう必要ありませんLC_ALL=C
  • zshから**/*.lua次に変更します。**/*
  • "*.lua" && filejust file(またはeven f)in rh(そして再びnot require)に変更してくださいLC_ALL=C
  • /オプションを有効'*.lua'または削除し、正規表現をパターンとして使用するように変更します。'*'fdfind-g--glob.

.mp3.flac名前が次のいずれかで終わるファイルを一致させるには、次のようにします.opus

  • '(' -name '*.flac' -o -name '*.mp3' -o -name '*.opus' ')' -type f標準findfind一部の実装でもサポートされていますが、-regex正規表現のスタイルと構文は実装ごとに異なります)。
  • **/*.(flac|opus|mp3)zshから
  • "*.@(flac|opus|mp3)" && filerh ( fnmatch()ksh88 拡張 glob パターン演算子をサポートするシステム) で使用される"\.(flac|opus|mp3)\z".re && fileか、サポートされていない場合に使用されます。
  • -ustf '\.(flac|open|mp3)$'fdfindで(globパターンの代わりに正規表現を使用)

大文字と小文字を区別せずに一致させるには

  • '(' -name '*.[fF][lL][aA][cC]' -o -name '*.[mM][pP]3' -o -name '*.[oO][pP][uU][sS]' ')' -type f標準からfind(一部の実装ではおよびfindサポートもあります)-iname-iregex
  • **/*.(#i)(flac|opus|mp3)zshから(set -o extendedglob事前に必要)
  • "*.@(flac|opus|mp3)".i && filerh ( fnmatch()ksh88 拡張 glob パターン演算子をサポートするシステム) で使用される"\.(flac|opus|mp3)\z".rei && fileか、サポートされていない場合に使用されます。
  • fdfindから-s/を削除します。パターンに大文字が含まれている場合は/--case-sensitiveも必要です-i--ignore-case

zsh を使用して何でもできるように配列のファイルのリストを取得するには:

set -o extendedglob
files=( /media/username/**/*.(#i)(flac|opus|mp3) )
do-anything-with $files

存在するbash

readarray -td '' < <(find ... -print0 | sort -z)
do-anything-with "${files[@]}"

(bash 4.4以降が必要です)。


1-eまた、拡張子の左側がUTF-8にデコードできないファイル名と一致しないようです(UTF-8を使用しないロケールでも)。しかし、拡張子以外の名前でのみ名前が付けられたファイルの場合、これは実際には理想的であると.lua思います。luaglobパターンベースのアプローチを使用してこの効果を得るには、パターンをまたは*?.luaに変更して、拡張子の前に少なくとも1文字(1バイトを含む)を?*.lua含めることができます。LC_ALL=C

おすすめ記事