home *** CD-ROM | disk | FTP | other *** search
- From: andrewt@watnow.waterloo.edu (Andrew Thomas)
- Newsgroups: alt.sources
- Subject: purge - Remove old emacs backup files safely
- Message-ID: <ANDREWT.90Apr23091019@watnow.waterloo.edu>
- Date: 23 Apr 90 14:10:19 GMT
-
-
- A couple of years ago I noticed that directories for really big
- projects edited using emacs tended to get cluttered by lots of .~n~
- files. I started typing things like rm *~, or rm *.~*~ to get rid
- of them, and noticed that a little typo had catastrophic effects.
-
- I wrote this program, which I called "purge", in C to do this stuff
- for me. At the time I didn't know awk or perl, so there is
- undoubtedly a shorter way to do it, but for what it's worth, here's my
- stuff. No complaints about programming style please: I know it's a
- little sloppy.
-
- What purge does:
- 1) Search a directory for all files ending in .~n~ or ~
- 2) establish that there is a more recently NUMBERED program of the
- same name, either with a .~n~ extension or with no extension.
- e.g., main.c.~2~ is newer than main.c.~1~ and main.c is
- newer than both of them.
- Purge does not check file dates, though it really should.
- 3) If a newer version can be found for a particular .~n~ or ~ file,
- then remove that file and report it.
- 4) Has the following arguments:
- directory name: Purge this directory.
- -c : confirm every file before erasing it.
- -r : recursively purge, starting at named or current
- directory.
- Flags and directory names may appear anywhere. Flags are not toggles.
-
- The thing I like about this is that it won't make stupid mistakes like
- "rm *". It also tries not to delete all copies of a file. File names
- with wild cards in them are not globbed.
-
- I make no claims to this code at all. If you want to say you wrote
- it, go ahead. I also take no responsibility for any of its actions.
-
- I have been using this on a uVaxII running Ultrix 2.0, a Sun 3
- running SUNOS3 and SUNOS4 and a SparcServer running SUNOS4. I have
- never had it do something unexpected in two years or service. That's
- more than I can say for my typing. :-)
-
- compile with:
- {g}cc -O -o purge purge.c
-
- ------------------- purge.c -------------------
- #include <stdio.h>
- #include <strings.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/dir.h>
- #include <sys/stat.h>
-
- void Usage (s)
- char* s;
- {
- fprintf (stderr, "Usage: %s [directory_name ...] [-c] [-r]\n", s);
- fprintf (stderr, " -c = confirm before erasing files\n");
- fprintf (stderr, " -r = recursively follow all subdirectories\n");
- exit (1);
- }
-
- int main(argc, argv)
- int argc;
- char *argv[];
- {
- int confirm = 0, i, recurse = 0, got_one = 0;
-
- for (i=1; i<argc; i++)
- {
- switch (argv[i][0])
- {
- case '-':
- switch (argv[i][1])
- {
- case 'c':
- confirm = 1;
- break;
- case 'r':
- recurse = 1;
- break;
- default:
- Usage (argv[0]);
- break;
- }
- break;
- }
- }
- for (i=1; i<argc; i++)
- {
- if (argv[i][0] != '-')
- {
- Do_Purge (argv[i], confirm, recurse);
- got_one = 1;
- }
- }
- if (!got_one) Do_Purge (".", confirm, recurse);
- return (0);
- }
-
- char* strsav(s)
- char* s;
- {
- char* t;
- t = (char*)malloc(strlen(s)+1);
- strcpy (t,s);
- return (t);
- }
-
- Do_Purge (directory, confirm, recurse)
- char* directory;
- int confirm;
- int recurse;
- {
- DIR *dirp;
- struct direct *entry;
- char *deletes[1000];
- int ndels = 0, i, slash = 0;
- char wholefile[160], instr[80], *this_file;
- int mycompare();
-
- if (!is_directory(directory))
- {
- fprintf (stderr, "File: %s - not a directory\n", directory);
- return;
- }
- if ((dirp = opendir(directory)) == NULL)
- {
- fprintf (stderr, "Could not open directory: %s\n", directory);
- return;
- }
-
- if (directory[strlen(directory)-1] != '/') slash = 1;
- for (entry = readdir(dirp); entry != NULL; entry = readdir(dirp))
- {
- sprintf (wholefile, "%s%s%s",
- directory,
- (slash ? "/" : ""),
- entry->d_name);
- if (recurse && is_directory(wholefile))
- {
- if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
- {
- Do_Purge (wholefile, confirm, recurse);
- }
- continue;
- }
- if (entry->d_name[strlen(entry->d_name)-1] == '~')
- {
- if (Has_More_Recent(entry, dirp))
- {
- deletes[ndels++] = strsav(wholefile);
- }
- }
- }
-
- qsort (deletes, ndels, sizeof(char *), mycompare);
-
- for (i=0; i<ndels; i++)
- {
- this_file = deletes[i];
- if (confirm)
- {
- fprintf (stdout, "Delete: %s ? (y/n/q/a) ", this_file);
- fscanf (stdin, "%s", instr);
- instr[0] = tolower(instr[0]);
- if (instr[0] == 'a')
- {
- confirm = 0;
- instr[0] = 'y';
- }
- else if (instr[0] == 'q')
- {
- i = ndels;
- }
- }
- else
- {
- fprintf (stdout, "Delete: %s\n", this_file);
- instr[0] = 'y';
- }
- if (instr[0] == 'y') unlink (this_file);
- }
- closedir (dirp);
- }
-
- int mycompare(a, b)
- char **a, **b;
- {
- return (strcmp(*a, *b));
- }
-
- Has_More_Recent (thisentry, dirp)
- struct direct *thisentry;
- DIR *dirp;
- {
- long spot;
- struct direct *rentry;
- char candidate[160];
- int a;
- char *directory;
-
- strcpy (candidate, thisentry->d_name);
- *index(candidate, '~') = '\0';
- if (candidate[a=strlen(candidate)-1] == '.') candidate[a] = '\0';
-
- spot = telldir(dirp);
- rewinddir (dirp);
- for (rentry = readdir(dirp); rentry != NULL; rentry = readdir(dirp))
- {
- if (rentry != thisentry)
- {
- if (!strcmp(rentry->d_name, candidate))
- {
- seekdir (dirp, spot);
- return (1);
- }
- }
- }
- seekdir (dirp, spot);
- return (0);
- }
-
- int is_directory (directory)
- char* directory;
- {
- struct stat stats;
- stat (directory, &stats);
- if (stats.st_mode & S_IFDIR) return (1);
- else return (0);
- }
-
- -----------------------------------------------
- --
-
- Andrew Thomas
- andrewt@watnow.waterloo.edu Systems Design Eng. University of Waterloo
- "If a million people do a stupid thing, it's still a stupid thing." - Opus
-