UNIX 命令树可以仅显示与模式匹配的目录吗?

UNIX 命令树可以仅显示与模式匹配的目录吗?

我试图弄清楚是否有一种方法可以让 UNIX 命令tree仅显示与特定模式匹配的目录。

% tree -d tstdir -P '*qm*' -L 1
tstdir
|-- d1
|-- d2
|-- qm1
|-- qm2
`-- qm3

5 directories

手册页显示有关开关的一些信息。

-P 模式 仅列出那些与通配符模式匹配的文件。注意:您必须使用 -a 选项来考虑那些以点.' for matching. Valid wildcard operators are*'(任何零个或多个字符)、?' (any single character),[...]'(括号之间列出的任何单个字符)开头的文件(可选 -(破折号)表示字符范围)可以使用:例如:[AZ]),和[^...]' (any single character not listed in brackets) and|' 分隔备用模式。

我假设关于...仅列出那些文件...是问题所在。我的解释是否正确,即此开关仅对文件进行模式匹配,并且不是目录?

答案1

没有办法tree独自做到这一点。模式不适用于目录,仅适用于文件。

但是,您可以通过获取 的目录列表tree,然后应用 的匹配模式来轻松完成您想要的任务grep

tree -d tstdir -L 1 | grep '*qm*'

答案2

有人提到过堆栈溢出trees手册页中,这就是为什么-P开关不排除与模式不匹配的内容的原因。

BUGS
   Tree  does not prune "empty" directories when the -P and -I options are
   used.  Tree prints directories as it comes to them, so  cannot  accumu‐
   late  information  on files and directories beneath the directory it is
   printing.

因此,似乎不可能tree使用 -P 开关来过滤其输出。

编辑#1

来自我在 SO 上发布的一个已关闭的问题。有人,@fhauri,发布了以下信息作为完成我尝试使用该tree命令执行的操作的替代方法。为了完整起见,我将它们添加到我的答案中。

-d切换询问到不是打印文件:

    -d     List directories only.

因此,如果您想使用它,您可以:

tree tstdir -P '*qm*' -L 1 | grep -B1 -- '-- .*qm'
|-- id1
|   `-- aqm_P1800-id1.0200.bin
--
|-- id165
|   `-- aqm_P1800-id165.0200.bin
|-- id166
|   `-- aqm_P1800-id166.0200.bin
--
|-- id17
|   `-- aqm_P1800-id17.0200.bin
--
|-- id18
|   `-- aqm_P1800-id18.0200.bin
--
|-- id2
|   `-- aqm_P1800-id2.0200.bin

总而言之,如果你使用-L 1

   -L level
          Max display depth of the directory tree.

你可以更好地使用(在bash中)这个语法:

cd tstdir
echo */*qm*

或者

printf "%s\n" */*qm*

如果只需要 dir:

printf "%s\n" */*qm* | sed 's|/.*$||' | uniq

无论如何,如果纯bash:

declare -A array;for file in  */*qm* ;do array[${file%/*}]='';done;echo "${!array[@]}"

这可以解释为:

cd tstdir
declare -A array          # Declare associative array, (named ``array'')
for file in  */*qm* ;do   # For each *qm* in a subdirectory from there
    array[${file%/*}]=''  # Set a entry in array named as directory, containing nothing
  done
echo "${!array[@]}"         # print each entrys in array.

...如果没有文件匹配模式,结果将显示*。因此,为了完美地完成工作,还需要做:

resultList=("${!array[@]}")
[ -d "$resultList" ] || unset $resultList

(这会比

declare -A array
for file in  */*qm*; do
    [ "$file" == "*/*qm*" ] || array[${file%/*}]=''
  done
echo "${!array[@]}"

相关内容