I am new to bash (but not to programming). I have a bash script that looks for all .txt
files in a project
for i in `find . -name "*.txt"`;
do
basename= "${i}"
cp ${basename} ./dest
done
However, I would like to get the .txt files only from a specific sub directory. For e.g this is my project structure:
project/
├── controllers/
│ ├── a/
│ │ ├── src/
│ │ │ ├── xxx
│ │ │ └── xxx
│ │ └── files/
│ │ ├── abc.txt
│ │ └── xxxx
│ └── b/
│ ├── src/
│ │ ├── xxx
│ │ └── xxx
│ └── files/
│ ├── abcd.txt
│ └── xxxx
├── lib
└── tests
I would like to get .txt
files only from controllers/a/files
and controllers/b/files
. I tried replacing find . -name "*.txt"
with find ./controllers/*/files/*txt
, it works fine, but errors out on GitHub actions with No such file or directory found
. So I'm looking for a more robust way of finding .txt
files from the subdirectory without having to hardcode the path in the for loop. Is that possible?
CodePudding user response:
You can use brace expansion for the search directory, e.g.
find ./project/controllers/{a,b} -type f -name "*.txt"
To select file only below ./project/controllers/a
and ./project/controllers/b
Additionally, your use of basename
would no longer be needed in your script (and cure the error with the ' '
(space) to the right of the '='
sign. Traditionally in bash, you will use process substitution to feed a while
loop rather than using a for
loop, e.g.
while read -r fname; do
# basename="${fname}" # note! no ' ' on either side of =
cp -ua "$fname" ./dest
done < <(find ./project/controllers/{a,b} -type f -name "*.txt")
Edit Based On Comment of Many Paths
If you have many controllers
not just a
and b
, then using the -path
option instead of the -name
options can provide a solution, e.g.
find . -path "./project/controllers/*/files/*.txt" -type f
would select any ".txt"
files below any directory below controllers
that contains a files
directory.
CodePudding user response:
It seems to me what you need is a simple cp
command,
cp project/controllers/*/files/*.txt ./dest/
if you want to copy only the files with .txt
extension under the directory files
(but not in its subdirectories, if any)