我有两个文件夹。我想在 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.ext
和subdir/bar.ext
indir1
都会删除相同的foo.ext
和subdir/bar.ext
in dir2
。
如果您想删除同名的文件,即使它们没有在dir1
和 的相同目录中找到dir2
(例如在上面的示例中,删除所有dir2/bar.ext
, dir2/any/level/of/subdirectory/foo.ext
)zsh
:
typeset -U names
names=( dir1/**/*.ext(ND^/:t) )
rm -f -- dir2/**/(${(~j[|])names})(D^/)
typeset -U names
给出独特的变量的属性,以便当分配为数组时,元素是唯一的(重复数据删除)。**/
任何级别(包括0级)子目录N
:N
ullglob: 如果没有匹配则不会抱怨。实际上,如果找不到任何.ext
文件,您可能会将其关闭,以便 shell 中止。D
:D
otglob: 不跳过隐藏文件。^/
就像find
s! -type d
排除类型的文件目录(如果不先删除其内容,则无法将其删除)。:t
: 获取t
ail,基本名称${(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.ext
和dir2/bar.ext
,而不是子目录中的那些),请删除上面命令**/
中的rm
或使用 GNU find
and 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
当您对它能按预期工作感到满意时将其删除