Reputation: 2285
I wanted to write a short script with the following structure:
find the right folders
cd into them
replace an item
So my problem is that I get the right folders from find
but I don't know how to do the action for every line find
is giving me. I tried it with a for loop like this:
for item in $(find command)
do magic for item
done
but the problem is that this command will print the relative pathnames, and if there is a space within my path it will split the path at this point.
I hope you understood my problem and can give me a hint.
Upvotes: 4
Views: 2695
Reputation: 8064
One way to do it is:
find command -print0 |
while IFS= read -r -d '' item ; do
... "$item" ...
done
-print0
and read ... -d ''
cause the NUL character to be used to separate paths, and ensure that the code works for all paths, including ones that contain spaces and newlines. Setting IFS
to empty and using the -r
option to read
prevents the paths from being modified by read
.
Note that the while
loop runs in a subshell, so variables set within it will not be visible after the loop completes. If that is a problem, one way to solve it is to use process substitution instead of a pipe:
while IFS= ...
...
done < <(find command -print0)
Another option, if you have got Bash 4.2 or later, is to use the lastpipe
option (shopt -s lastpipe
) to cause the last command in pipelines to be run in the current shell.
Upvotes: 1
Reputation: 77059
If the pattern you want to find is simple enough and you have bash 4 you may not need find
. In that case, you could use globstar
instead for recursive globbing:
#!/bin/bash
shopt -s globstar
for directory in **/*pattern*/; do
(
cd "$directory"
do stuff
)
done
The parentheses make each operation happen in a subshell. That may have performance cost, but usually doesn't, and means you don't have to remember to cd
back each time.
If globstar
isn't an option (because your find
instructions are not a simple pattern, or because you don't have a shell that supports it) you can use find
in a similar way:
find . -whatever -exec bash -c 'cd "$1" && do stuff' _ {} \;
You could use +
instead of ;
to pass multiple arguments to bash each time, but doing one directory per shell (which is what ;
would do) has similar benefits and costs to using the subshell expression above.
Upvotes: 0
Reputation: 554
You can run commands with -exec option of find directly:
find . -name some_name -exec your_command {} \;
Upvotes: 3