我遇到以下问题。我有一个目录结构,想要删除名为 的目录中的所有内容Caches
。除所有名为的目录外,所有内容都应删除Snapshots
。我不知道如何做到这一点寻找或我知道的任何其他命令。
我问的原因是:在 iOS 上,每个应用程序都有自己的 Caches 目录。这些有时无法正确清除,具体取决于应用程序。有了这个答案的解决方案,当设备的驱动器安装在另一台计算机上时,例如使用 FUSE (iExplorer),人们将能够清除 iOS 上的缓存,从而优化磁盘空间。
这是我到目前为止所拥有的:
find . 2>/dev/null -type d -name "Caches" -maxdepth 3 -print
这会返回类似以下内容的内容:
./Library/Caches
当我执行 a 时,ls ./Library/Caches
我会看到所有内容和Snapshots
目录,我想排除它们,因为最终我想要-delete
除此之外的所有内容。
我想要这样的东西:
Before: After:
. .
├── a ├── a
│ ├── a │ ├── a
│ └── Caches │ └── Caches
│ ├── a │ └── a
│ │ └── Snapshots │ └── Snapshots
│ │ └── a │ └── a
│ ├── b └── b
│ │ └── a └── c
│ └── c
└── b
├── c
└── Caches
├── a
│ └── foo
│ └── a
└── b
└── a
答案1
我对问题的措辞有点困惑。如果您想要删除目录中./Library/Caches
除名为 的单个文件夹之外的所有内容Snapshots
,则无需使用find
.在 中bash
,shell glob 是最简单的方法:
shopt -s extglob # probably already enabled
echo Library/Caches/!(Snapshots)
如果这会打印您要删除的所有文件/目录,则替换echo
为rm -f --
.
如果您想要保留Snapshots
目录树中不同级别的多个目录,那么使用 GNU您可以执行以下操作:./Library/Caches
find
find Library/Caches ! -path '*Snapshots*'
这应该打印所有文件/目录,不包括Snapshots
路径中的文件/目录。它将包含包含目录(或其子目录包含)的目录Snapshots
,但find ... -delete
不会删除这些目录,而是打印一条错误,指出它们不为空。一旦你感到高兴,就添加-delete
到最后。
需要注意的是,这将留下任何文件命名Snapshots
完好。如果这是一个问题,请改为:
find Library/Caches \( ! -path '*Snapshots*' -o -type f -name Snapshots \)
高兴的时候再补充-delete
。
答案2
find . -depth -print0 | perl -0lne '
if ("$_/" =~ m{/Caches(/.*)}s && $1 !~ m{/Snapshots/}) {rmdir $_ or unlink $_}'
如果你find
不支持-print0
,你可以用 替换它-exec printf '%s\0' {} +
。
这个想法是打印以 NUL 结尾的文件列表(因为 0 是文件路径中唯一不能出现的字节)并使用perl
带有选项-n
的-0
为每个文件名运行一些代码($_
设置为文件名)。
使用 时-depth
,文件将在其父目录之前打印。如果文件或目录depth
的路径/Caches/
后面不包含/Snapshosts/
.
答案3
我不是find
巫师,所以我不想说你不能用 来做到这一点find
,但我确实知道可以用几行 来完成bash
。鉴于我正确理解您的目录结构:
#!/bin/bash
for i in Library/Caches/*; do
if [[ -d "$i" ]]; then
[[ "$i" =~ "Snapshots" ]] || echo "rm-ing $i" # change to rm -rf "$i" to use
fi
done
该for
语句返回 中的每个项目Library/Caches/
。该if [[ -d "$i" ]]
语句检查每个项目是否是一个目录,如果是,则检查它的名称以查看它是否包含“Snapshots” [[ "$i" =~ "Snapshots" ]]
。因为没有运算符可以否定正则表达式匹配,例如!=~
,所以我过去常常在上一个命令不成功时||
执行rm
,例如目录名称不包含快照。
这将在任何使用的现代系统上运行bash
,但它必须有bash
。另外,您可能需要尝试一下目录结构,但这应该适合您。
答案4
第一部分:找到名为caches的目录并对它们执行一些操作
find . -name Caches -type d -exec … \;
第二部分:遍历缓存目录,并删除所有内容,但保留Snapshots
子目录及其内容(以及通向它们的路径)。进行深度优先遍历,这样目录一旦变空就可以删除。
find /path/to/Caches -depth -name Snapshots -type d -prune \
-o \( -type d -empty -o ! -type d \) -delete
现在将它们组合在一起。
find . -name Caches -type d -exec
find {} -depth -name Snapshots -type d -prune \
-o \( -type d -empty -o ! -type d \) -delete