我有很多目录和子目录。我想从目录中递归删除一个特定文件(如果它是目录中唯一的文件)。还假设该目录中没有子目录。因此,总而言之,假设是:
- 文件名为 README.TXT(不区分大小写)
- 找到该文件的目录中没有其他文件或目录
结构:
mkdir usecase
cd usecase
mkdir destroy_this
touch destroy_this/readme.txt
mkdir do_not_destroy_this
touch do_not_destroy_this/readme.txt
touch do_not_destroy_this/something-else.txt
mkdir do_nothing
cd do_nothing
mkdir rm_this
touch rm_this/README.TXT
cd ..
mkdir do_nothing_here
cd do_nothing_here
mkdir has_sub_dir
touch README.TXT
cd ..
运行上面的代码会产生这样的树结构:
$ tree .
.
`-- usecase
|-- destroy_this
| `-- readme.txt
|-- do_not_destroy_this
| |-- readme.txt
| `-- something-else.txt
|-- do_nothing
| `-- rm_this
| `-- README.TXT
`-- do_nothing_here
|-- has_sub_dir
`-- README.TXT
这是我到目前为止所得到的:
find . -type f -iname "readme.txt" -exec sh -c 'ls $(dirname "{}") | wc -l' \;
我的想法是,我计算文件和目录的数量,如果是一个,则删除该文件。
答案1
您所拥有的一切是一个良好的起点。如果您修改了您的内容,-exec
您可以引入一个if/then
构造,该构造允许您根据计数的状态是否为 1 进行操作。
$ find . -type f -iname "readme.txt" -exec \
sh -c 'if [ "$(ls $(dirname "{}") | wc -l)" -eq "1" ]; \
then echo "yes"; \
else echo "no"; \
fi' \;
no
yes
yes
no
这样我们就可以扩展echo "yes"
命令来执行文件的实际删除。像这样的东西rm "{}"
应该可以解决问题。
例子
$ find . -type f -iname "readme.txt" -exec \
sh -c 'if [ "$(ls $(dirname "{}") | wc -l)" -eq "1" ]; \
then echo "removing {}.."; rm "{}"; \
else echo "no"; \
fi' \;
no
removing ./usecase/destroy_this/readme.txt..
removing ./usecase/do_nothing/rm_this/README.TXT..
no
第二次运行上述命令确认文件不再存在:
$ find . -type f -iname "readme.txt" -exec \
sh -c 'if [ "$(ls $(dirname "{}") | wc -l)" -eq "1" ]; \
then echo "removing {}.."; rm "{}"; \
else echo "no"; \
fi' \;
no
no
答案2
find . -type f -iname "readme.txt" -exec sh -c '
for f do ls -1qap ${f%/*} |
grep -v "\(readme.txt\$\|/\$\|.\{1,2\}\$\)" &&
echo rm "$f" ; done' \{\} +