Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 在bash中查找文件失败_Linux_Bash_Scripting - Fatal编程技术网

Linux 在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

我正在用Bash编写一个脚本,目的是清除目录中的所有垃圾文件。我创建了一个包含所有要删除的文件模式的数组

例子 假设我有一个名为
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”,实际列表的大小是示例列表的两倍。”