hGen
hGen

Reputation: 2285

find folders and cd into them

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 findbut I don't know how to do the action for every line findis 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

Answers (3)

pjh
pjh

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

kojiro
kojiro

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

gurel_kaynak
gurel_kaynak

Reputation: 554

You can run commands with -exec option of find directly:

find . -name some_name -exec your_command {} \;

Upvotes: 3

Related Questions