Linux 在bash中查找文件失败
我正在用Bash编写一个脚本,目的是清除目录中的所有垃圾文件。我创建了一个包含所有要删除的文件模式的数组 例子 假设我有一个名为Linux 在bash中查找文件失败,linux,bash,scripting,Linux,Bash,Scripting,我正在用Bash编写一个脚本,目的是清除目录中的所有垃圾文件。我创建了一个包含所有要删除的文件模式的数组 例子 假设我有一个名为temp的目录,里面有与下面数组中的模式匹配的文件 fileJunk=(".inca*" ".cat*" "*Cat%" "*inca*") 然后我对下面的每一项进行查找 for j in "${fileJunk[@]}" do myList=( `find temp -maxdepth 2 -type f -iname $j` ) for z in
temp
的目录,里面有与下面数组中的模式匹配的文件
fileJunk=(".inca*" ".cat*" "*Cat%" "*inca*")
然后我对下面的每一项进行查找
for j in "${fileJunk[@]}"
do
myList=( `find temp -maxdepth 2 -type f -iname $j` )
for z in "${myList[@]}"
do
rm $z >& /dev/null
if [ $? -eq 0 ]
then
echo -e "SUCCESS: File $j was deleted\n"
fi
done
done
问题是find
命令会查找除印加应该匹配的文件之外的所有文件
只有在用双引号括起*inca*
时,才可以直接在命令行上执行此操作。因此,我将数组更改为:
fileJunk=(".inca*" ".cat*" "*Cat%" "\"*inca*\"")
这样,我将把“*inca*”
传递给find
命令,而不是*inca*
。但是,这仅在命令行上有效,而不使用脚本
更多信息
最后,我要澄清的问题是:为什么我在shell中使用命令
find
和“*inca*”
时,它能工作,而在脚本中却不能工作?在Bash中处理变量时,几乎应该总是将任何变量放在双引号中。我会像这样更改您的代码:
for j in "${fileJunk[@]}"
do
myList=( $(find temp -maxdepth 2 -type f -iname "$j") )
for z in "${myList[@]}"
do
rm -f "$z" >& /dev/null
if [ $? -eq 0 ]
then
echo -e "SUCCESS: File $j was deleted\n"
fi
done
done
例如,如果我们要拉出第一个For
循环并运行它,则回显find
命令:
$ fileJunk=(".inca*" ".cat*" "*Cat%" "*inca*")
$ for j in "${fileJunk[@]}";do echo "find temp -maxdepth 2 -type f -iname \"$j\""; done
find temp -maxdepth 2 -type f -iname ".inca*"
find temp -maxdepth 2 -type f -iname ".cat*"
find temp -maxdepth 2 -type f -iname "*Cat%"
find temp -maxdepth 2 -type f -iname "*inca*"
以下是希望在此处运行的find
命令的形式
调试Bash
如果您仍然遇到问题,即使是引用,我会启用您的脚本,使其冗长。您可以通过设置set-x
来完成此操作
例如:
$ set -x; for j in "${fileJunk[@]}";do find /tmp -maxdepth 2 -type f -iname "$j"; done; set +x
+ set -x
+ for j in '"${fileJunk[@]}"'
+ find /tmp -maxdepth 2 -type f -iname '.inca*'
+ for j in '"${fileJunk[@]}"'
+ find /tmp -maxdepth 2 -type f -iname '.cat*'
+ for j in '"${fileJunk[@]}"'
+ find /tmp -maxdepth 2 -type f -iname '*Cat%'
+ for j in '"${fileJunk[@]}"'
+ find /tmp -maxdepth 2 -type f -iname '*inca*'
+ set +x
您希望避免在可能较大的目录树上多次运行
find
在括号中运行find
,将导致shell尝试将其输出解析为标记。如果find
查找包含空格或换行符的文件名,则此操作将失败
抑制rm
的输出,然后打印自己的输出消息,这似乎是错误的。如果删除文件失败,您想知道它失败的原因。如果成功时还需要消息,请使用-v
find temp -maxdepth 2 -type f \(
-iname ".inca*" -o -iname ".cat*" -o \
-iname "*Cat%" -o -iname "*inca*" \) \
-exec rm -f -v {} +
如果要从表达式数组生成find
命令,请重试
inames=()
joiner='('
for j in "${fileJunk[@]}"; do
inames+=($joiner "-iname" "$j")
joiner='-o'
inames+=(')')
find temp -maxdepth 2 -type f "${inames[@]}" \
-exec rm -f -v {} +
您会注意到,为了防止shell扩展它,需要引用“$j”的值,这也是您最初尖锐问题的答案。另见
另一方面,shell的流控制语句已经在幕后为您检查了$?
,因此您几乎不需要自己显式地检查它。任何看起来像
command
if [ $? -eq 0 ]; then
写得更好
if command; then
因为
if
及其朋友while
和until
的目的是运行命令并检查其退出状态。如果在find命令中引用它,而不是在数组中添加引号,会发生什么?i、 e.find temp-maxdepth 2-typef-iname“$j”
没有合理的理由将find
输出捕获到一个变量,然后循环到该变量上。但是是的,@tripleee的+1-我正在向OP展示如何做,因为这就是所要求的。这将是一个理智的理由8-。@triplee:我不是疯子,我只是一个bash脚本的初学者,还不知道它背后的所有技巧;-)感谢你的链接,这是非常有用的。无意冒犯,这是一个常见的反模式使用一个变量来存储你实际上不需要的东西OP试图编辑这个答案;我想下面是一个评论当我创建一个列表时,它的目标是让用户能够轻松地更改它。循环find命令不会给我带来任何问题,除了“inca”,实际列表的大小是示例列表的两倍。”