web-dev-qa-db-ja.com

サブディレクトリをnレベルだけリストする

Festivalは、次のサンプルディレクトリ構造にボイスパックデータを格納します。

/usr/share/festival/voices/<language>/<voicepack name>

潜在的に多数の<voicepack name>サブディレクトリ内の<language>のみを出力する最も簡単な1行(好ましくはlsを使用)は何ですか?

67
user66001

私はFedoraを使用しており、これらのボイスパックは少し異なる場所にあります。

$ ls /usr/share/festival/lib/voices/*/ -1 | grep -vE "/usr|^$"
kal_diphone
ked_diphone
nitech_us_awb_arctic_hts
nitech_us_bdl_arctic_hts
nitech_us_clb_arctic_hts
nitech_us_jmk_arctic_hts
nitech_us_rms_arctic_hts
nitech_us_slt_arctic_hts

次のように変更するだけです。

$ ls /usr/share/festival/voices/*/ -1 | grep -vE "/usr|^$"

検索を使用する

このマナーでのlsの使用は、lsの出力を解析するのが難しいため、通常は嫌われます。次のように、findコマンドを使用することをお勧めします。

$ find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
    -type d -exec basename {} \;
nitech_us_awb_arctic_hts
nitech_us_bdl_arctic_hts
nitech_us_slt_arctic_hts
nitech_us_jmk_arctic_hts
nitech_us_clb_arctic_hts
nitech_us_rms_arctic_hts
ked_diphone
kal_diphone

検索とベース名の詳細

このコマンドは、このディレクトリに対して正確に2レベルの深さのファイルへの完全パスのリストを作成することによって機能します。

/usr/share/festival/lib/voices

このリストは次のようになります。

$ find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 
/usr/share/festival/lib/voices/us/nitech_us_awb_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_bdl_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_slt_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_jmk_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_clb_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_rms_arctic_hts
/usr/share/festival/lib/voices/english/ked_diphone
/usr/share/festival/lib/voices/english/kal_diphon

ただし、これらのディレクトリの最後の部分であるリーフノードが必要です。したがって、basenameを使用して解析することができます。

$ basename /usr/share/festival/lib/voices/us/nitech_us_awb_arctic_hts
nitech_us_awb_arctic_hts

これらすべてをまとめると、findコマンドで各2レベルの深いディレクトリをbasenameコマンドに渡すことができます。表記basename {}は、これらのベース名変換を行うものです。 Findは-execスイッチを介して呼び出します。

87
slm

最も簡単です

ls -d /usr/share/festival/voices/*/*

これは、シェルによって/usr/share/festival/voices/のすべてのサブディレクトリに展開され、それらの各サブディレクトリのコンテンツに展開されます。

タイトルが示すように特定のレベルにのみ降りたい場合は、GNUやBSDのようなfindの実装をいくつか使用します。

find /usr/share/festival/voices/ -mindepth 2 -maxdepth 3 -type d

これにより、-type dのために/usr/share/festival/voices/のサブディレクトリにあるが、3レベル下(mindepth 2)未満のすべてのディレクトリ(maxdepth 3)が見つかります。 man findから:

   -maxdepth levels
          Descend at most levels (a non-negative integer) levels of direc‐
          tories below the command line arguments.  -maxdepth 0
           means only apply the tests and  actions  to  the  command  line
          arguments.

   -mindepth levels
          Do  not apply any tests or actions at levels less than levels (a
          non-negative integer).  -mindepth  1  means  process  all  files
          except the command line arguments.
28
terdon

受け入れられる回答 は正しく機能しますが、サブディレクトリごとに新しいbasenameプロセスを生成するため、多少非効率的です。

find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
    -type d -exec basename {} \;

可能な場合は、findに組み込まれている機能を使用して、プロセスの生成によるコストを回避することをお勧めします。 findには、-printfアクションを使用して印刷出力を変更するかなり広範な機能があります。デフォルトの-printアクションはパス全体を出力しますが、-printfとフォーマット文字列を使用すると、パスの一部を選択して出力できます。先頭のディレクトリなしでパスのファイル名部分のみを抽出するには(basenameと同様)、フォーマット文字列は%fです。各ファイル名の後に改行を入れるには、次のように\nを含めます。

$ find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
    -type d -printf '%f\n'
nitech_us_awb_arctic_hts
nitech_us_bdl_arctic_hts
nitech_us_slt_arctic_hts
nitech_us_jmk_arctic_hts
nitech_us_clb_arctic_hts
nitech_us_rms_arctic_hts
ked_diphone
kal_diphone
6
Michael Henry

TLDR;この質問のtitleに基づいてここに来たばかりの人; 「サブディレクトリを深さnレベルのみ一覧表示する」:使用

find -maxdepth N

ここで、Nは任意の数値です。

2
Gabriel Staples