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

@f-hauri看起来有最好的理由来解释为什么这不能像手册页中可用的开关所想象的那样工作tree。我在错误部分错过了这一点。

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不是完成包含过滤列表的最佳方法,但独占过滤列表将是使用该-I开关的替代方法。

相反,shell 通配符、find 命令或 Perl 脚本将是完成此任务的更合适方法。看@f-hauri 的对于其中一些替代方法来说,这是一个很好的答案。

答案1

是的,这是一个漏洞。从手册页:

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.

... 无论如何,-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[@]}"

答案2

你可以用我的阿尔博命令。安装:

ln -s "$PWD"/arbo.py ~/bin/arbo

现在你可以这样做:

find tstdir -maxdepth 1 -iname '*qm*' |arbo --color

输出看起来像这样,颜色与 ls 相同:

git arbo
bedup
├─ __init__.py
├─ __main__.py
├─ platform/__init__.py
├─ termupdates.py
├─ test_bedup.py
└─ tracking.py
setup.py
tox.ini

相关内容