在bash脚本中使用find命令,仅对目录出现" No such file or directory"错误?

20

更新 2014-03-21

我意识到我的效率还不够高,因为我需要"擦洗"的所有磁盘都在 /media 目录下,而且命名为 "disk1"、"disk2"、"disk3" 等等。以下是最终脚本:

DIRTY_DIR="/media/disk*" 
find $DIRTY_DIR -depth -type d -name .AppleDouble -exec rm -rf {} \;
find $DIRTY_DIR -depth -type d -name .AppleDB -exec rm -rf {} \;
find $DIRTY_DIR -depth -type d -name .AppleDesktop -exec rm -rf {} \;
find $DIRTY_DIR -type f -name ".*DS_Store" -exec rm -f {} \;
find $DIRTY_DIR -type f -name ".Thumbs.db" -exec rm -f {} \; #  I know, I know, this is a Windows file.

接下来可能只是清理代码,添加日志和报告结果的功能(通过电子邮件或其他方式); 排除系统和目录; 并允许人们自定义文件/目录列表。

感谢大家的帮助!

更新

在采纳所有人提供的有用建议之前,我进行了一些测试,其结果非常有趣(见下文)。

作为测试,我运行了以下命令:

root@doi:~# find /media/disk3 -type d -name .AppleDouble -exec echo rm -rf {} \;

结果(这是我预期的):

rm -rf /media/disk3/Videos/Chorus/.AppleDouble

但是,当我运行实际命令(没有echo):

root@doi:~# find /media/disk3 -type d -name .AppleDouble -exec rm -rf {} \;

我收到了相同的“错误”输出:

find: `/media/disk3/Videos/Chorus/.AppleDouble': No such file or directory

我加引号是因为很明显该文件夹已被删除,立即运行以下命令进行验证:

root@doi:~# find /media/disk3 -type d -name .AppleDouble -exec rm -rf {} \;
root@doi:~# 
似乎find命令存储了原始结果,对其进行了删除目录的操作,但是之后又尝试删除它?还是说rm-f选项,用于忽略不存在的文件和参数,被忽略了?我注意到当我单独运行rm命令而不使用find命令运行测试时,一切都正常。因此,直接运行rm -rf ... \nonexistent_directory,即使"non_existent_directory"不存在,也没有返回任何错误,而直接运行rm -r \nonexistent_directory则提供了预期的结果:
rm: cannot remove 'non_existent_directory': No such file or directory

我应该使用-delete选项,而不是-exec rm ...选项吗?我想尽可能地让脚本适用于那些没有find命令的-delete选项的系统。

最后,如果/media/disk1/media/disk2等在/media/storage下组合成AUFS文件系统,这是否会影响find命令对磁盘本身进行操作呢?感谢大家迄今为止所有的帮助。完成后,我将发布这个脚本。

原始帖子

我正在编写一个bash脚本,在我的Lubuntu文件共享中删除一些OS X遗留文件。 然而,当执行以下命令时:

...
BASE_DIR="/media/disk" # I have 4 disks: disk1, disk2, ...   
COUNTER=1

while [ $COUNTER -lt 5 ]; do      # Iterate through disk1, disk2, ...
   DIRTY_DIR=${BASE_DIR}$COUNTER     # Look under the current disk counter /media/disk1, /media/disk2, ...
   find $DIRTY_DIR -name \.AppleDouble -exec rm -rf {} \;    # Delete all .AppleDouble directories
   find $DIRTY_DIR -name ".*DS_Store" -exec rm -rf {} \;     # Delete all .DS_Store and ._.DS_Store files
   COUNTER=$(($COUNTER+1))
done
...

我看到以下输出:

find: /media/disk1/Pictures/.AppleDouble: 没有那个文件或目录

在我添加-exec rm ...部分之前,脚本找到了/media/disk1/Pictures/.AppleDouble目录。 脚本对于删除DS_Store文件有效,但是为了查找目录,我漏掉了什么?

我担心过多地更改-exec部分会错误地销毁目录。


第一个[find]命令应该加上-type d标志,第二个命令则应该加上-type f标志(第二个命令也不需要在rm后面加上r)。这样做的目的是防止删除与目录同名的文件或反之,并避免不必要的递归查找。 - Reinstate Monica Please
2
尝试使用“-exec echo rm -rf {} ;”进行调试。我会添加“-depth”以确保在删除“./a/b/X”之前删除“./a/b/X/c/X”。 - glenn jackman
@BroSlow 感谢你发现了这些问题。我知道我应该更加小心,并已将其添加到我的脚本中。 - El Jorge
@glenn 在这种情况下,如果我不想保留.AppleDouble下的任何内容,删除./a/b/X是否会有问题? - El Jorge
1
你可能遇到的问题是,当你不使用-delete选项时,你没有隐含的-depth选项;因此,你最终会删除已经被前几次查找命令删除过的文件。更多信息请参见http://unix.stackexchange.com/questions/170999/。 - 7heo.tk
相关链接:https://unix.stackexchange.com/questions/115863/delete-files-and-directories-by-their-names-no-such-file-or-directory/115869#115869 - Ciro Santilli OurBigBook.com
2个回答

55

简而言之,如果您正在使用find删除目录,请传递-prune

对于其他遇到这个问题的人。可以运行这样的示例:

find /media/disk3 -type d -name .AppleDouble -exec rm -rf {} \;

会导致类似的错误

rm: cannot remove 'non_existent_directory': No such file or directory

当使用 find 查找和删除目录时,你经常会遇到这个错误,因为 find 存储要处理子目录的目录,然后使用 exec 删除它,然后尝试遍历不再存在的子目录。

你可以使用 -maxdepth 0-prune 来防止出现这个问题。像这样:

find /media/disk3 -type d -name .AppleDouble -prune -exec rm -rf {} \;

现在它可以无错误地删除目录。万岁! :)


3

在shell glob中,您无需转义DOT,因为这不是正则表达式。因此,请使用.AppleDouble而不是\.AppleDouble

find $DIRTY_DIR -name .AppleDouble -exec rm -rf '{}' \;

提示:我在你的脚本中没有看到任何地方对$COUNTER进行增加。


对不起,我忘记把它放在“编辑”版本的脚本中。实际上它是在里面的,只是当我删除“无关部分”的脚本时忘记保留它了。 - El Jorge
好的,我现在看到你修改过的问题了。你可以尝试使用以下命令:find /media/disk3 -type d -name .AppleDouble -exec rm -rf '{}' \; -prune - anubhava
所以事实证明这是一些事情的组合 - 请看我上面做的。 - El Jorge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接