我需要使用仅在运行时已知的值为find
建立参数列表。我正在尝试使用数组来执行此操作。
以下是使用硬编码值的简化版本。当我回显出命令它似乎是正确的(当我手动运行它时,它做了我所期望的)。当它进入for循环时,它似乎正在运行find
(因为对于其他用户拥有的目录,我可以看到与Permission denied
相同的错误,就像我手动运行时一样)。但是在for循环中,它不会回显出手动运行找到的任何.txt
文件。
我做错了什么?
#!/bin/bash
args=(/tmp -iname \"*.txt\")
#args+=(-o -iname \"*.jpg\")
echo command will be: find ${args[@]}
for f in $( find ${args[@]} ); do
echo found $f
done
下面接受的答案正确地确定了问题。但是,如果我添加一个额外的-iname
子句,我的脚本会“忽略”除了最后一个,如下所示:
#!/bin/bash
args=($1)
args+=(-maxdepth $2)
args+=(-iname "*$3")
args+=(-o -iname "*$4")
echo command will be: find "${args[@]}"
find "${args[@]}" -print 2>/dev/null | while read -r f; do
echo found "$f"
done
例如,当使用/home/me 2 .jpg .png
调用时,这正确地表示该命令将为find /home/me -maxdepth 2 -iname *.jpg -o -iname *.png
,但之后我的脚本仅回显它找到的.png
个文件。
答案 0 :(得分:3)
你不应该逃避引号。这将使它们成为文字,因此它将尝试查找名称实际上以双引号开头和结尾的文件。
args=(/tmp -iname "*.txt")
然后你需要在${args[@]}
周围加上引号,告诉shell在扩展数组时它应该重新引用它们:
find "(" "${args[@]}" ")" -print | while read -r f
do
echo found "$f"
done
答案 1 :(得分:1)
Bash4可以使用shopt -s globstar
递归地扩展globs
只需使用array=(/tmp/**/*.txt)
即可获取所有元素。