Unix递归删除文件和文件夹

时间:2013-09-18 02:56:42

标签: bash unix recursion

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

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

3 个答案:

答案 0 :(得分:3)

你有

for file in $1

...

recursive $file #recursively call

这实际上变成了重复

for file in $file

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

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

同时为$file...的情况添加测试,或从我的$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

有关详情,请参阅this question

答案 1 :(得分:2)

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

例如,以下命令应从当前目录中以递归方式删除名为foo.txt的“仅文件”,并显示要删除的文件列表。

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

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

  

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

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

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

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

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

#!/bin/sh

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

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

答案 2 :(得分: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


}