bash 在 dir1 中使用“find”并删除 dir2 中的这些文件

bash 在 dir1 中使用“find”并删除 dir2 中的这些文件

我有两个文件夹。我想在 dir1 中递归查找具有特定扩展名的文件,并从 dir2 中删除在 dir1 中找到的文件。我认为这可以通过 find 中的 -exec 命令来完成。从 dir1 中删除它非常简单 - 但如何为 dir2 做到这一点呢?

查找 /home/admin/.cache/yay/ -name '*.pkg.tar.zst' -exec basename {} ; (现在删除/tmp/test/中找到的文件)

答案1

看起来更容易xargs

(cd dir1 && find . -name '*.ext' ! -type d -print0) |
  (cd dir2 && xargs -r0 rm -f --)

对于每个foo.extsubdir/bar.extindir1都会删除相同的foo.extsubdir/bar.extin dir2

如果您想删除同名的文件,即使它们没有在dir1和 的相同目录中找到dir2(例如在上面的示例中,删除所有dir2/bar.ext, dir2/any/level/of/subdirectory/foo.extzsh

typeset -U names
names=( dir1/**/*.ext(ND^/:t) )
rm -f -- dir2/**/(${(~j[|])names})(D^/)
  • typeset -U names给出独特的变量的属性,以便当分配为数组时,元素是唯一的(重复数据删除)。
  • **/任何级别(包括0级)子目录
  • N: Nullglob: 如果没有匹配则不会抱怨。实际上,如果找不到任何.ext文件,您可能会将其关闭,以便 shell 中止。
  • D: Dotglob: 不跳过隐藏文件。
  • ^/就像finds! -type d排除类型的文件目录(如果不先删除其内容,则无法将其删除)。
  • :t: 获取tail,基本名称
  • ${(j[string])array}将数组的元素与string中间元素连接起来。使用 时~,连接字符串被视为 glob 运算符,因此我们最终得到一个(foo.ext|bar.ext|...)glob。

使用匿名函数(并u用参数扩展标志代替typeset -U)在一个命令上打了同样的高尔夫球:

(){rm -f dir2/**/(${(~j[|])${(u)@}})(D^/)} dir1/**/*.ext(D^/:t)

如果有大量不同的名称,另一种更有效的方法是使用关联数组:

typeset -A to_remove
: dir1/**/*.ext(ND^/e['to_remove[$REPLY:t]=1'])
rm -f -- dir2/**/*.ext(De['(( $to_remove[$REPLY:t] ))']^/)

如果您只想在根目录中删除它们dir2(在上面的示例中,仅删除dir2/foo.extdir2/bar.ext,而不是子目录中的那些),请删除上面命令**/中的rm或使用 GNU findand sort

(cd dir1 && find . -name '*.ext' -printf '%f\0') |
  LC_ALL=C sort -zu |
  (cd dir2 && xargs -r0 rm -f --)

答案2

从 dir1 查找文件路径。将路径剥离为仅文件名。从 dir2 中删除每个找到的文件:

find /home/admin/.cache/yay/ -type f -name '*.pkg.tar.zst' -exec sh -c 'for f in "$@"; do echo rm -f -- "/path/to/dir2/${f##*/}"; done' _ {} +

如果你不想要 shell 循环,

find /home/admin/.cache/yay/ -type f -name '*.pkg.tar.zst' -exec sh -c 'echo rm -f -- "/path/to/dir2/${1##*/}"' _ {} \;

echo当您对它能按预期工作感到满意时将其删除

相关内容