Reputation: 9989
I need to write a Bash script (preferably a one-liner) to find all the subdirectories under the current directory which contain any files with a certain file extension, namely .tf
. The tricky part is that there may be more than one .tf
file in a folder, and I need the folders - not the filenames.
So for example, suppose my directory contents look something like this:
.
├── 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
In this case I would want the command to return terraform/module
, terraform/environments/prod
, and terraform/environments/staging
. I also need a way to filter out certain directories that should never be included. In the example above note that I did not include the dot-file directory .terraform
.
I already know how to write the following find command, which can find the .tf
files themselves:
find . -name '*.tf' -not -path '*.terraform*'
However I'm not sure how to write a command to find the directories which contain those files.
Upvotes: 7
Views: 4116
Reputation: 785008
This find
command should also work:
find . -type d -not -path '*/.terraform*' \
-exec bash -c 'shopt -s failglob; ( : "$1"/*.tf ) 2>/dev/null && echo "$1"' - {} \;
failglob
returns failure if glob pattern fails.find
command scans each directory in current path and bash -c
checks for presence of *.tf
files in each directory.Upvotes: 1
Reputation: 85767
You could do it like this:
shopt -s globstar # to enable support for **
for i in **/*.tf; do echo "${i%/*}"; done | sort -u
If you don't have **
enabled already, the shopt
line will do it for you.
We iterate over all *.tf
files in all subdirectories and print out their directory names (by chopping off all trailing /*
components). sort -u
is used to remove duplicates.
Upvotes: 0
Reputation: 311476
You can use find's -printf
action to print out just the directory name, and then remove duplicates:
find . -name '*.tf' -not -path '*.terraform*' -printf '%h\n' | sort -u
The -printf '%h\n'
prints out the name of the directory containing matched files, while the sort -u
at the end removes duplicates.
Upvotes: 14