我想编写一个包含以下结构的简短脚本:
find the right folders
cd into them
replace an item
所以我的问题是我从find
获得了正确的文件夹,但我不知道如何为find
给我的每一行执行操作。我用这样的for循环尝试了它:
for item in $(find command)
do magic for item
done
但问题是这个命令将打印相对路径名,如果我的路径中有空格,它将在此时分割路径。
我希望你理解我的问题,并能给我一个提示。
答案 0 :(得分:2)
您可以直接使用-exec选项运行命令:
find . -name some_name -exec your_command {} \;
答案 1 :(得分:1)
一种方法是:
find command -print0 |
while IFS= read -r -d '' item ; do
... "$item" ...
done
-print0
和read ... -d ''
导致NUL字符用于分隔路径,并确保代码适用于所有路径,包括包含空格和换行符的路径。将IFS
设置为空并使用-r
选项read
可阻止read
修改路径。
请注意,while
循环在子shell中运行,因此在循环完成后,其中设置的变量将不可见。如果这是一个问题,解决它的一种方法是使用进程替换而不是管道:
while IFS= ...
...
done < <(find command -print0)
如果你有Bash 4.2或更高版本,另一个选择是使用lastpipe
选项(shopt -s lastpipe
)来使管道中的最后一个命令在当前shell中运行。
答案 2 :(得分:0)
如果您要查找的模式足够简单并且您有bash 4,则可能不需要find
。在这种情况下,您可以使用globstar
代替递归globbing:
#!/bin/bash
shopt -s globstar
for directory in **/*pattern*/; do
(
cd "$directory"
do stuff
)
done
括号使每个操作都在子shell中进行。这可能会有性能成本,但通常不会,并且意味着您不必每次都记得cd
。
如果globstar
不是一个选项(因为您的find
说明不是一个简单的模式,或者因为您没有支持它的shell),您可以使用{ {1}}以类似的方式:
find
您可以使用find . -whatever -exec bash -c 'cd "$1" && do stuff' _ {} \;
而不是+
每次都将多个参数传递给bash,但每个shell执行一个目录(这是;
会做的事情)具有类似的好处和成本使用上面的子shell表达式。