List folders which contain only a subfolder named Attic

With bash, GNU find, and 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 )

The first find prints basenames (-printf '%h\n') of everything, files and directories, in the repository. sort | uniq -u then prints directories with exactly one descendant, file or directory.

Then the second find prints the basenames of the Attic directories. The intersection of this set to the set above (i.e. comm -12) are exactly the directories with only an Attic descendant.

This of course happily ignores things like symlinks and other fun, and filenames with embedded newlines. You shouldn't have those in a CVS repo anyway.


Find all Attic folders in . without any siblings, in bash:

find . -type d -name Attic -print0 | while read -d $'\0' DIR ;\
    do [[ $(ls -1 "$DIR/.." | wc -l) -eq 1 ]] && echo "$DIR" ; done

Replace echo with your favorite file handling command ;-).


The first part seems to be easiest to do with a bit of 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)

Run it like this:

./script.py /path/to/CVS/repo

To delete the directories, assuming your files don't have newlines embedded in names, and assuming a cooperating xargs (i.e. one with the -d option):

./script.py /path/to/CVS/repo | xargs -d '\n' rm -rf

With a non-cooperating xargs you could modify the script to print NUL-terminated strings:

#!/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")

Then you'd use xargs -0 to kill the directories:

./script.py /path/to/CVS/repo | xargs -0 rm -rf

To kill empty directories after that:

find /path/to/CVS/repo -depth -type d -empty -delete