查找比匹配目录更深一层的目录列表


13

我正在尝试获取特定文件夹中包含的目录的列表。

给定这些示例文件夹:

foo/bar/test
foo/bar/test/css
foo/bar/wp-content/plugins/XYZ
foo/bar/wp-content/plugins/XYZ/js
foo/bar/wp-content/plugins/XYZ/css
baz/wp-content/plugins/ABC
baz/wp-content/plugins/ABC/inc
baz/wp-content/plugins/ABC/inc/lib
baz/wp-content/plugins/DEF
bat/bar/foo/blog/wp-content/plugins/GHI

我想要一个将返回的命令:

XYZ
ABC
DEF
GHI

本质上,我正在寻找wp-content / plugins /中的文件夹

使用find使我最接近,但是我不能使用-maxdepth,因为该文件夹与我要搜索的位置存在一定距离。

运行以下命令以递归方式返回所有子目录。

find -type d -path *wp-content/plugins/*

foo/bar/wp-content/plugins/XYZ
foo/bar/wp-content/plugins/XYZ/js
foo/bar/wp-content/plugins/XYZ/css
baz/wp-content/plugins/ABC
baz/wp-content/plugins/ABC/inc
baz/wp-content/plugins/ABC/inc/lib
baz/wp-content/plugins/DEF
bat/bar/foo/blog/wp-content/plugins/GHI

Answers:


14

只需添加一个,-prune这样发现的目录就不会进入以下目录:

find . -type d -path '*/wp-content/plugins/*' -prune -print

您需要引用它,*wp-content/plugins/*因为它也是一个外壳程序。

如果你只想要的目录名称,而不是它们的完整路径,以及GNU find,你可以代替-print-printf '%f\n'或假设文件路径不包含换行符,管上面的命令的输出awk -F / '{print $NF}'sed 's|.*/||'(也假设文件路径包含仅有效字符)。

zsh

printf '%s\n' **/wp-content/plugins/*(D/:t)

**/是子目录的任何级别(功能起源于zsh早期睡衣,现在在大多数其他炮弹发现喜欢ksh93tcshfishbashyash在某些选项,虽然通常情况下),(/)只选择类型的文件目录D包括隐藏(点)的,:t以获取尾部(文件名)。


此发现会将dirs中的换行符转换为?。对于bash(在问题中标记为),此方法有效
艾萨克(Isaac)

@sorontar,只输出输出到终端,而不输出到类似此处的管道时find,输出?或任何替换字符或以任何形式转义非可打印字符的实现。
斯特凡Chazelas

答案中的第一个(也是唯一一个非zsh)命令没有管道,这是我测试过的命令,也是更改换行符的命令。如您所说,当通过管道传输时:“假设文件路径不包含换行符”,因此,您已经承认使用换行符也会失败。
艾萨克(Isaac)

@sorontar,对不起,我以为您在第二部分发表评论说,它可以正常工作,因为换行符将被转义,因此不会破坏我们正在做的假设sed/ awk所有文件都在一行上。现在,有人可能会争辩说,获得a ABC?BCDABC\nBCD用于交互式/终端输出将比获得2 ABCBCD一行用于名为dir的目录更有用$'ABC\nBCD。这是在用户演示的水平,我们也可以指出,对于一个名为$'AB\bC',当输出去一个终端,你会看到AC没有这样的?替代...
斯特凡Chazelas

使用-prune查找并使用printf修改输出格式,这正是我所要的。很好,谢谢!
尼克

4

严格地说:

shopt -s globstar
printf "%s\n" **/wp-content/plugins/*

印刷品:

bat/bar/foo/blog/wp-content/plugins/GHI
baz/wp-content/plugins/ABC
baz/wp-content/plugins/DEF
foo/bar/wp-content/plugins/XYZ

要么

shopt -s globstar
for d in **/wp-content/plugins/*; do printf "%s\n" ${d##*/}; done

印刷品:

GHI
ABC
DEF
XYZ

不,那也将在目录内打印文件。请阅读我的答案。
艾萨克(Isaac)

好点子; 谢谢!我已经重新创建了它们的目录结构,但是没有在其中放置测试文件。
杰夫·谢勒

4

您可能需要find递归,例如:

find / -type d -path *wp-content/plugins -exec find {} -maxdepth 1 -mindepth 1 -type d \;

3

对于Bash:简单(适用于带有空格换行符的文件/目录):

shopt -s globstar                    # allow ** for several dirs.
a=(**/wp-content/plugins/*/)         # capture only wanted dirs.
a=("${a[@]%/}")                      # remove trailing slash (dirs) `/`.
printf '%s\n' "${a[@]##*/}"          # print only the last dir name.

列印:

GHI
ABC
DEF
XYZ

即使已创建文件。


请注意,它不会在隐藏目录中查找,不会跳过隐藏文件(dotglob如果不需要,请参见该选项),除了目录以外,**还包括指向目录的符号链接(还将遍历bash 4.2及更早版本中的符号链接)。
斯特凡Chazelas

@StéphaneChazelas隐藏文件?这个问题只要求Dirs。是的,可以独立选择隐藏的目录(如果需要,可以作为一项功能)。是的,在当前版本的bash中,符号链接不是横向的。
艾萨克(Isaac)

1
请不要将我的评论视为侵略。我赞成您的回答,并在下面添加了注释,以指出一些不一定显而易见的事实。find不排除任何文件。globs排除了点文件,值得指出的是两者之间的区别。
斯特凡Chazelas

3

tree命令正是为此目的而设计的。深度可以用-L标志控制。这是我维护的本地Wordpress网站上的示例:

$ tree -L 1 wp-content/
wp-content/
├── index.php
├── plugins
└── themes

2 directories, 1 file

$ tree -L 2 wp-content/
wp-content/
├── index.php
├── plugins
   ├── akismet
   ├── contact-form-7
   ├── index.php
   └── wordpress-seo
└── themes
    ├── index.php
    ├── twentyfifteen
    └── twentysixteen

11 directories, 3 files

$ tree -L 1 wp-content/plugins/
wp-content/plugins/
├── akismet
├── contact-form-7
├── index.php
└── wordpress-seo

5 directories, 1 file

1

基于DopeGhoti的答案,匹配循环如何:

find / -type d -iregex '.*/wp-content/plugins' -print0 | while read -r -d $'\0' D; do
    find "$D" -maxdepth 2 -mindepth 1
done

这样做的原因是,您可能会发现它与多个-exec字符混淆/繁琐,同时仍然避免了包含\ n''等特殊文件名的问题。-print0将在结果之间使用空分隔符。


0

在您开始的基础上:

find -type d -path *wp-content/plugins/* | egrep -o "wp-content/plugins/[^/]+($|/)" | sed -r "s~wp-content/plugins/([^/]+)($|/)~\1~" | uniq  

egrep抓取* wp-content / plugins / *以及直到下一个斜杠/或$结尾的所有字符-包括所需的部分。

sed使用〜分隔符,使用第一组括号()选择所需的部分,并使用\ 1(您想要的内容)替换所有内容

uniq过滤掉重复的结果

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.