1

所以我正在开发一个递归删除文件和文件夹的程序。出于某种原因,我陷入了无限循环。请指出我错在哪里。

for file in $1
       do
               if [ -f $file ] #If it is a file just delete it
               then
                       echo "delete $file"

               elif [ -d $file ] #if it is a folder
               then
                        #look inside and see if it is empty or not
                       if [ "$(ls -A $file)" ] 

                       then
                                recursive $file #recursively call 
                       else
                                #if the folder is empty just delete it
                               echo "delete $file"
                       fi
               fi

       done
4

3 回答 3

3

你有

for file in $1

...

recursive $file #recursively call

这实际上变成了重复

for file in $file

也就是说,它不断重复相同的第一个目录条目。您需要再次考虑整个函数,或者在递归调用中传递不同的参数,或者不要使用forover $1。最简单的可能是更改for(未经测试):

for file in "$1/*" "$1/.*"

还添加测试 case where $fileis .or ,或从 my..中删除部分。$file/.*for


关于调试 bash 脚本,以下两个set选项通常很有用,例如,您可以将它们添加到脚本的开头。

set -x # print every final command line when it is executed
set +x # turn -x off

set -v # print script lines as they are read
set +v # turn -v off

有关此的更多信息,请参阅此问题

于 2013-09-18T03:18:30.083 回答
2

如果我了解您要实现的目标,我怀疑您最好使用该find命令而不是滚动您自己的 shell 脚本。

例如,以下命令应该foo.txt从当前目录开始以递归方式删除命名为“just files”,并显示正在删除的文件列表。

find . -name foo.txt -type f -exec rm -v {} \;

您可以man find了解有关如何使用此工具的详细信息,但基本上选项大致如下:

查找路径[路径...] [表达式]

其中path是递归搜索的一个或多个起始目录,而expression是要执行的条件或操作的列表。

在上面的例子中,我们有两个明显-name foo.txt的条件——表示文件名,-type f表示“这是一个普通文件”。表达式中的第三个选项执行以转义分号结尾的命令行,替换{}为找到的每个文件的名称。

此外,在处理多个文件名时,请注意不要解析ls. 有关详细信息,请阅读Greg 的 wiki 中的 ParsingLs

最后,如果您尝试创建一个需要删除多个文件名的脚本,您可以使用以下内容:

#!/bin/sh

for file in $@; do
  find . -type f -name "$file" -exec rm -v {} \;
done

请注意,这也适用于更简单的 POSIX 样式 shell,它不需要 bash。

于 2013-09-18T07:16:37.637 回答
0

所以我有点重写它。该代码效率不高,但可以完成工作。

recursive()
{
        # create a file
        touch $HOME/temp_file #create a file
        tree -fi $1 > $HOME/temp_file #tree it up and pump it in the file

        touch $HOME/temp_file
        tree -fid $1 > $HOME/temp_file #tree it up and pump it in the file

        count=$(wc -l $HOME/temp_file | cut -d " " -f1)

        #loop thru the file that contains only directory 
        for ((i=1;i<=$[$count-2];i++))
        do
               args=$(sed -n $i"p" $HOME/temp_file) #grab line by line
               if [ -d $args ] #if it is a folder
                then
                        if recurse_down $args # if recurse down interactive flag is set
                        then
                                if  [ "$(ls -A $args)" ] #if dir is not empty
                                then
                                        touch $HOME/temp_file2
                                #store only file name in another file this time
                                ls $args | grep -v ^d > $HOME/temp_file2

                                        count2=$(wc -l $HOME/temp_file2 |  cut -d " " -f1)
                                        for ((z=1;z<=$count2;z++))
                                        do
                                                file=$(sed -n $z"p" $HOME/temp_file2)
                                                echo "deleting  $file"

                                                #call delete function and pass in filename
                                                # and the path of it
                                                delete $file $args  
                                        done
                                else
                                        echo "Empty dir. Just delete it"
                                        delete $args
                                fi
                         else
                                exit
                        fi

                fi



         done


}

delete()
{
        # $2 for path and $1 for filename
        echo "1 is $1"
        echo "2 is $2"
        File=$2/$1
        echo "Fileeeeeeee is $File"
        #echo "node is $node"

        node=$(stat -c%i $File) #get inode number of the file
        opFile="$recycleBin"/$(basename "$File")"_$node" #append it
        echo "opFile is $opFile"
        no_basename=$(basename "$File") #get basename

        # it will be like f8_1287540:/home/waiyan.hein/bin/d9/d1/f8
        echo "${no_basename}_$node:`pwd`/$File" >> $HOME/.restore.info

        #now move the file into destination folder
        mv $File $opFile


}
于 2013-09-20T03:22:36.523 回答