我使用以下命令来查找并删除一组子卷:
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 …
find
find
btrfs subvolume delete
find
告诉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
,但失败并出现“没有这样的文件或目录”错误,因为它已经消失了。
您可以通过使用-depth
with 来解决此问题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-*
。在bash
shell 中,设置nullglob
shell 选项将导致 shell 删除任何不匹配的通配模式,而不是保留未展开的模式。
如果该命令btrfs subvolume delete
能够采用多个路径名作为参数,您甚至可能只需要这样做
shopt -s failglob
btrfs subvolume delete /.snapshots/backup-*
...如果没有与给定的通配模式匹配的路径名,shellfailglob
中的 shell 选项将阻止命令执行。bash