我试图弄清楚是否有一种方法可以让 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[@]}"
)