n レベルの深さのサブディレクトリのみを一覧表示します

n レベルの深さのサブディレクトリのみを一覧表示します

Festival は、次の例のディレクトリ構造にボイスパック データを保存します。

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

潜在的に多数のサブディレクトリすべてでlsだけを出力する最も単純なワンライナー ( を使用するのが望ましい) は何ですか?<voicepack name><language>

答え1

私は 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

find & basename の詳細

このコマンドは、このディレクトリに対して正確に 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スイッチを介してこれを呼び出します。

答え2

一番簡単なのは

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

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

findタイトルが示唆するように、 GNU や BSD などの実装を使用して特定のレベルまで降りたいだけの場合:

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

これにより、-type dのサブディレクトリ内にあるが、3 レベルより下 ( )未満のすべてのディレクトリ ( ) が検索されます。/usr/share/festival/voices/mindepth 2maxdepth 3man 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.

答え3

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

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

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

$ 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

答え4

bash を使用していて、ls を使用するだけのシンプルなものを探している人向け:

ls -d $PWD/*

エイリアスを作成するときは(~/.bash_aliases など)、必ず一重引用符を使用してください。

alias ldf='ls -d $PWD/*'

引用符で囲まないと、シェルは ls を実行しようとします。

二重引用符で囲むと、エイリアスの作成時の $PWD の値を持つエイリアスが作成されます。

必要に応じて $(pwd) を使用することもできますが、bash が $PWD を提供している場合にサブシェルを生成する意味がわかりません。

関連情報