所以我正在开发一个递归删除文件和文件夹的程序。出于某种原因,我陷入无休止的循环中。请指出我错在哪里。
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
答案 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
}