使用 find 清理脚本 - 没有这样的文件或目录

使用 find 清理脚本 - 没有这样的文件或目录

我使用以下命令来查找并删除一组子卷:

find /.snapshots/ -name backup-* -type d -exec btrfs subvolume delete {} \;

它有效,但我从 find 中得到了意外的输出:

Delete subvolume (no-commit): '/.snapshots/backup-24-11-2021'    
find: ‘/.snapshots/backup-24-11-2021’: No such file or directory    
Delete subvolume (no-commit): '/.snapshots/backup-25-11-2021'    
find: ‘/.snapshots/backup-25-11-2021’: No such file or directory
    

我不是unix专业人士,所以这对我来说有点令人困惑,为什么会发生这种情况?

答案1

find到达时/.snapshots/backup-24-11-2021,它会按照 的指示检查它是否是一个目录-type d。它是一个目录,因此按照 的指示find运行。完成后,刚刚到达一个目录,因此它会递归到该目录。毕竟,递归到目录是.但该目录刚刚被删除(由)。因此注意到有问题并报告。btrfs subvolume delete /.snapshots/backup-24-11-2021-exec …findfindbtrfs subvolume deletefind

告诉find您不要在您要删除的快照下进行递归。这通常适用于查找要删除的整个目录树。

find /.snapshots/ -name 'backup-*' -type d -exec btrfs subvolume delete {} \; -prune

(注意:我还修复了子句周围缺少的引号-name。没有引号,运行backup-*时会展开,因此如果当前目录有匹配的文件,或者如果您使用的 shell 出错,则find该命令将不会执行预期的操作backup-*在不匹配的全局上。)

但实际上,这可能完全是错误的命令。您指示find在 下到处查看/.snapshots。例如,如果有一个目录/.snapshots/saved-for-posterity/usr/src/backup-app,您的命令指示find调用btrfs subvolume delete /.snapshots/saved-for-posterity/usr/src/backup-app,这是没有意义的。假设所有快照都是 的子目录/.snapshots,请传递-maxdepth 1以避免进一步递归:

find /.snapshots/ -maxdepth 1 -name 'backup-*' -type d -exec btrfs subvolume delete {} \;

唯一的区别是

btrfs subvolume delete /.snapshots/backup-*

是如果当前没有备份,则btrfs subvolume delete使用文字参数进行调用。/.snapshots/backup-*

答案2

您收到错误消息是因为您find在有机会查看目录内部之前删除了这些目录。当find完成包含现在已删除目录的目录时,它尝试输入 eg backup-24-11-2021,但失败并出现“没有这样的文件或目录”错误,因为它已经消失了。

您可以通过使用-depthwith 来解决此问题find,这使得实用程序对目录进行深度优先搜索。只有在查看了该路径下的所有其他目录/.snapshots/backup-25-11-2021后,才会发生查找和删除eg 的情况。find

find /.snapshots -depth -name 'backup-*' -type d \
    -exec btrfs subvolume delete {} \;

另请注意,我们需要引用测试的参数,-name因为它包含文件名通配符。

另一种方法是使用-prune,即find在找到该路径时从搜索树中删除该路径,这样find就不会尝试继续深入其中。

find /.snapshots -name 'backup-*' -type d -prune \
    -exec btrfs subvolume delete {} \;

第三种方法是,如果所有backup-*目录始终直接位于 下,则根本/.snapshots不使用:find

shopt -s nullglob
for dir in /.snapshots/backup-*; do
    btrfs subvolume delete "$dir"
done

上面的 shell 循环将调用btrfs subvolume delete与模式匹配的所有目录/.snapshots/backup-*。在bashshell 中,设置nullglobshell 选项将导致 shell 删除任何不匹配的通配模式,而不是保留未展开的模式。

如果该命令btrfs subvolume delete能够采用多个路径名作为参数,您甚至可能只需要这样做

shopt -s failglob
btrfs subvolume delete /.snapshots/backup-*

...如果没有与给定的通配模式匹配的路径名,shellfailglob中的 shell 选项将阻止命令执行。bash

相关内容