使用递归方式删除所有具有相应 "*.bar" 文件的 "*.foo" 文件。

5
如何递归地删除所有以.foo结尾的文件,而这些文件有一个同名但以.bar结尾的兄弟文件?例如,考虑以下目录树:
.
├── dir
│   ├── dir
│   │   ├── file4.bar
│   │   ├── file4.foo
│   │   └── file5.foo
│   ├── file2.foo
│   ├── file3.bar
│   └── file3.foo
├── file1.bar
└── file1.foo

在这个例子中,由于存在兄弟文件file{1,3,4}.barfile.foofile3.foofile4.foo将被删除。file{2,5}.foo应该保留,最终结果如下:
.
├── dir
│   ├── dir
│   │   ├── file4.bar
│   │   └── file5.foo
│   ├── file2.foo
│   ├── file3.bar
└── file1.bar

3
感谢出色的问题图示,给你点赞。 - shellter
还要感谢tree的存在。:P http://linux.die.net/man/1/tree - knpwrs
3个回答

6

在您尝试以下findrm命令之前,请务必先备份内容。

使用以下find命令:

find . -name "*.foo" -execdir bash -c '[[ -f "${1%.*}.bar" ]] && rm "$1"' - '{}' \;

1
干得好!只有一个提示给OP,为了匹配xargs的性能,可以使用“+”符号来并行处理文件。 - jaypal singh
+1 我不理解 ${1%.*}。我尝试了一下,${1%} 会返回扩展名。我在哪里可以找到更多关于这个的信息? - Tiago Lopo
@Tiago:感谢你能在man bash中找到。请查看“参数扩展”部分。 - anubhava

2
while IFS= read -r FILE; do
    rm -f "${FILE%.bar}".foo
done < <(exec find -type f -name '*.bar')

或者

find -type f -name '*.bar' | sed -e 's|.bar$|.foo|' | xargs rm -f

1
在bash 4.0及更高版本以及zsh中:
shopt -s globstar   # Only needed by bash
for f in **/*.foo; do
    [[ -f ${f%.foo}.bar ]] && rm ./"$f"
done

在zsh中,你可以定义一个选择性模式,仅匹配以.foo结尾的文件,前提是存在相应的.bar文件,这样rm命令只会被调用一次,而不是每个文件调用一次。
rm ./**/*.foo(e:'[[ -f ${REPLY%.foo}.bar ]]':)

1
以防万一,我会在这些通配符文件名之前始终使用“--”,用户可能希望设置GLOB_DOTS(以获得类似于“find”的结果):rm -- ** / *.foo(De:'[[ -f $ {REPLY%.foo} .bar]]':) - vinc17
好的建议。我已经编辑了答案,使用./代替--,因为这将适用于任何实现的rm - chepner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接