仅列出 n 级深的子目录

use*_*001 82 ls bash

Festival 将语音包数据存储在以下示例目录结构中:

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

在所有潜在的众多子目录中,最简单的单行(最好使用ls)是什么?<voicepack name><language>

slm*_*slm 102

我在 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
Run Code Online (Sandbox Code Playgroud)

您可以像这样修改它:

$ ls /usr/share/festival/voices/*/ -1 | grep -vE "/usr|^$"
Run Code Online (Sandbox Code Playgroud)

使用查找

使用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
Run Code Online (Sandbox Code Playgroud)

查找和基本名称的详细信息

此命令的工作原理是生成一个文件的完整路径列表,这些文件的深度正好是该目录的 2 级:

/usr/share/festival/lib/voices
Run Code Online (Sandbox Code Playgroud)

该列表如下所示:

$ 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
Run Code Online (Sandbox Code Playgroud)

但是我们想要这些目录的最后一部分,即叶节点。所以我们可以利用basename来解析它:

$ basename /usr/share/festival/lib/voices/us/nitech_us_awb_arctic_hts
nitech_us_awb_arctic_hts
Run Code Online (Sandbox Code Playgroud)

综上所述,我们可以让find命令将每个 2 级深层目录传递给basename命令。符号basename {}是进行这些基本名称转换的内容。Find 通过它的-exec开关调用它。


ter*_*don 34

最简单的是

ls -d /usr/share/festival/voices/*/*
Run Code Online (Sandbox Code Playgroud)

这被 shell 扩展到所有子目录/usr/share/festival/voices/,然后扩展到每个子目录的内容。

如果您只想按照标题建议的那样下降到特定级别,并使用findGNU 和 BSD 之类的一些实现:

find /usr/share/festival/voices/ -mindepth 2 -maxdepth 3 -type d
Run Code Online (Sandbox Code Playgroud)

这会发现所有的目录(-type d)是在一个子目录/usr/share/festival/voices/,因为mindepth 2但不深于3个水平下降(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.
Run Code Online (Sandbox Code Playgroud)


Mic*_*nry 7

接受的答案工作正常,但有些低效的,因为它产生一个新basename的每个子目录的过程:

find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
    -type d -exec basename {} \;
Run Code Online (Sandbox Code Playgroud)

如果可能,最好使用内置功能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
Run Code Online (Sandbox Code Playgroud)

  • @slm 的回答得到了很好的解释,并涵盖了将 `find` 与任意外部命令一起使用的更一般模式;对于内置在“find”中的操作来说,它的效率较低。我曾考虑在他的回答中添加评论,但这需要比我更多的声誉。无需更改您接受的答案,因为当前接受的答案是正确的、解释清楚的,并且可用作更一般情况的模式;我只是想指出,对于这种特定情况,有一种更有效的方法。 (2认同)

Gab*_*les 6

TLDR;对于那些刚刚根据这个问题的标题来到这里的人;到“仅列出 n 级 [s] 深的子目录”:使用

find -maxdepth N
Run Code Online (Sandbox Code Playgroud)

哪里N有任何数字。


例子:

find -maxdepth 4
Run Code Online (Sandbox Code Playgroud)

列出 4 级深的所有文件和文件夹。


如果您需要搜索特定文件或文件夹,只需将其通过管道传输到grep. 前任:

find -maxdepth 4 | grep -i some_file_name
Run Code Online (Sandbox Code Playgroud)

请注意,-i以上使 grep 搜索来自find命令大小写 'i'nsensitive的文件和文件夹名称。