如何在Bash中查找包含特定文件扩展名的所有文件夹?

6
我需要编写一个Bash脚本(最好是一行命令),以查找当前目录下包含特定文件扩展名的所有子目录,即.tf。麻烦的部分是,一个文件夹中可能有多个.tf文件,而我需要的是文件夹 - 而不是文件名。
例如,假设我的目录内容如下:
.
├── docs
│   ├── README.md
│   └── diagram.png
├── project
│   └── main.py
├── Makefile
├── terraform
│   ├── environments
│   │   ├── prod
│   │   │   └── main.tf
│   │   └── staging
│   │       └── main.tf
│   └── module
│       ├── ecs.tf
│       ├── rds.tf
│       ├── s3.tf
│       ├── security_group.tf
│       ├── sqs.tf
│       └── variable.tf
├── tests
|   └── test_main.py
└── .terraform
    └── ignore_me.tf

在这种情况下,我希望该命令返回terraform/moduleterraform/environments/prodterraform/environments/staging。我还需要一种方法来过滤掉绝不应包含的某些目录。在上面的示例中,请注意我没有包括点文件目录.terraform
我已经知道如何编写以下find命令,该命令可以找到.tf文件本身:
find . -name '*.tf' -not -path '*.terraform*'

然而我不确定如何编写命令来查找包含这些文件的目录。

4个回答

10
您可以使用find命令的-printf选项来仅打印出目录名称,然后删除重复项:
find . -name '*.tf' -not -path '*.terraform*' -printf '%h\n' | sort -u
-printf '%h\n'会打印出匹配文件所在目录的名称,sort -u则可去除重复项。

1
如果目录名包含换行符,则仍会产生不正确的输出。显然,这是一个不常见的边缘情况,但值得指出。 - tripleee
另外,Alpine上不提供printf选项。 - Simon Campano
问题没有指定需要使用Alpine。如果您想在Alpine上使用此解决方案,请先执行“apk install findutils”。 - larsks

1

try this:

shopt -s globstar

echo **/*.tf | xargs dirname | sort -u

1
如果任何文件或目录名称包含空格,则此方法无法正常工作。 - melpomene
我同意。你的答案更完整。我建议在循环中添加[[ -f“$i”]] || continue,以处理找不到任何内容且i为** / * .tf或存在扩展名为.tf的目录的情况。 - Craig

1
这个 find 命令也应该可以工作:
find . -type d -not -path '*/.terraform*' \
-exec bash -c 'shopt -s failglob; ( : "$1"/*.tf ) 2>/dev/null && echo "$1"' - {} \;
  • failglob会在文件名匹配失败时返回失败。
  • find命令扫描当前路径中的每个目录,bash -c检查每个目录中是否存在*.tf文件。

0
你可以这样做:
shopt -s globstar  # to enable support for **

for i in **/*.tf; do echo "${i%/*}"; done | sort -u

如果您还没有启用**,则shopt行将为您完成。
我们遍历所有子目录中的所有*.tf文件,并打印出它们的目录名称(通过去掉所有尾随的/*组件)。使用sort -u来删除重复项。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接