在迁移到 git 之前,我正在清理 CVS 存储库。作为准备工作的一部分,我需要查找(并可能删除)仅包含Attic
文件夹的任何文件夹。
我的 unix-fu 并不强大,但这是我尝试过的,这不起作用,但希望能传达意图。
shopt -s globstar
for file in **/*
do
if [ -d "$file" ];then
if [`ls | wc -l` == 1 && `ls Attic | wc -l` == 1]; then
((echo Attic-only folder))
fi
fi
done
第二部分是找到任何空的文件夹(或文件夹链)。
例如,如果/foo/bar/Attic
被删除,并且/foo/bar
现在都是空的,那么我们也杀死树的那部分。
背景:我正在尝试清理 CVS 存储库以迁移到 git。 CVSAttic
为已删除的文件创建一个文件夹。在过去的十年里,发生了一些糟糕的事情。我完全了解风险和影响。我已经备份了数据并且正在制作副本。
答案1
与bash
、GNUfind
和comm
:
comm -12 \
<( find /path/to/CVS/repo -printf '%h\n' \
sort | uniq -u ) \
<( find /path/to/CVS/repo -name Attic -type d -printf '%h\n' | \
sort )
第一个find
打印存储库中所有内容、文件和目录的 basename
s ( )。然后打印只有一个后代、文件或目录的目录。-printf '%h\n'
sort | uniq -u
然后第二个find
打印目录basename
的 s Attic
。该集合与上面集合的交集(即comm -12
)正是仅具有Attic
后代的目录。
这当然很高兴地忽略了符号链接和其他有趣的东西,以及带有嵌入换行符的文件名。无论如何,您不应该将它们放在 CVS 存储库中。
答案2
在 bash 中查找没有任何同级的所有Attic
文件夹.
:
find . -type d -name Attic -print0 | while read -d $'\0' DIR ;\
do [[ $(ls -1 "$DIR/.." | wc -l) -eq 1 ]] && echo "$DIR" ; done
替换echo
为您最喜欢的文件处理命令;-)。
答案3
第一部分似乎最容易用一些 Python 来完成:
#!/usr/bin/env python
import os, sys
for topdir in sys.argv:
for root, dirs, files in os.walk(topdir):
if not files and len(dirs) == 1 and dirs[0] == 'Attic':
print os.path.join(root)
像这样运行它:
./script.py /path/to/CVS/repo
要删除目录,假设您的文件名称中没有嵌入换行符,并假设有一个合作xargs
(即带有该-d
选项的文件):
./script.py /path/to/CVS/repo | xargs -d '\n' rm -rf
如果不合作,xargs
您可以修改脚本以打印NUL
终止字符串:
#!/usr/bin/env python
from __future__ import print_function
import os, sys
for topdir in sys.argv:
for root, dirs, files in os.walk(topdir):
if not files and len(dirs) == 1 and dirs[0] == 'Attic':
print(os.path.join(root), end="\0")
然后你可以用来xargs -0
杀死目录:
./script.py /path/to/CVS/repo | xargs -0 rm -rf
之后要杀死空目录:
find /path/to/CVS/repo -depth -type d -empty -delete
答案4
试试这个命令
find $(find . -type d -exec bash -c "echo -ne '{} '; ls '{}' | wc -l" \; | awk '$NF==1{print $1}') -name Attic -exec rm -r {} \;