/*
From: Nat Friedman <ndf@aleph1.mit.edu> Date: Thu, 25 Jul 1996 04:02:31 -0400
To: steve@media.mit.edu

Here's ptrenumber.  I clocked myself - it took exactly 11 minutes to
write it.  I think that's a record for me.  It works perfectly on this
end.. here's how:

[ndf@aleph1 test]$ ls
pic0001.ppm  pic0043.ppm  pic3001.ppm  pic3081.ppm  pic7038.ppm
[ndf@aleph1 test]$ ../ptrenumber pic.ppm 4
../ptrenumber: Scanning directory for matching files... Found 5 matching files.
../ptrenumber: Sorting file names..
format_string: %s%04d.%s
../ptrenumber: Renaming pic0001.ppm to pic0000.ppm...
../ptrenumber: Renaming pic0043.ppm to pic0001.ppm...
../ptrenumber: Renaming pic3001.ppm to pic0002.ppm...
../ptrenumber: Renaming pic3081.ppm to pic0003.ppm...
../ptrenumber: Renaming pic7038.ppm to pic0004.ppm...
[ndf@aleph1 test]$ ls
pic0000.ppm  pic0001.ppm  pic0002.ppm  pic0003.ppm  pic0004.ppm
[ndf@aleph1 test]$ 

I think you'll find the interface fairly easy to work with.  Be sure to
read the comments in the code - there are a few options, etc.

Good luck with it.
*/

/*
 * Usage: ptrenumber basename numdigits
 *
 * Example: ptrenumber foo.ppm 3
 *   will renumber foo001.ppm, foo103.ppm, foo733.ppm to
 *   foo000.ppm foo001.ppm foo002.ppm
 *
 *
 * Nota Bene: This program MUST be run from the directory in which
 * the files to be renamed are stored.
 *
 * Nat Friedman <ndf@mit.edu>
 *
 */

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>

/* Change this if you like. */
#define VERBOSE

/* Making these global is a quick way to get this program finished
   in under 10 minutes. */
char * input_prefix;
char * input_suffix;


void
usage(char * cmd)
{
  fprintf(stderr, "\nUsage: %s basename numdigits\nExample: ptrenumber "
	  "foo.ppm 3\nwill renumber foo001.ppm foo103.ppm foo733.ppm to\n"
	  "foo000.ppm foo001.ppm foo002.ppm respectively.\n", cmd);
  exit(1);
}

int
my_compare_function(const void * a, const void * b)
{
  if ((*(int *)a)<(*(int *)b))
    return -1;
  if ((*(int *)a)==(*(int *)b))
    return 0;
  return 1;
}

/* strdup() isn't sufficiently ubiquitous */
char *
my_strdup(char * s)
{
  char * dup_s;

  dup_s=(char *)malloc(sizeof(char)*(strlen(s)+1));
  strcpy(dup_s, s);
  return dup_s;
}

void
get_file_list(char * input_template, int ** input_file_nums,
              int * num_input_files, int num_digits)
{
  struct dirent * dirent;
  char num_string[10];
  DIR * dir;
  int i,j;

  input_prefix=my_strdup(input_template);

  /* NB: Here we assume that the suffix begins with a "."
     Note that filenames such as pict001..ppm will not work :-) */
  input_suffix=strrchr(input_prefix, '.');
  if (input_suffix==NULL)
    {
      fprintf(stderr, "It is the unfortunate truth that ptrenumber only "
	      "allows\nyou to work with filenames of the form string1."
	      "string2, such\n as \"image.ppm\".  We apologize for the "
	      "inconvenience.\n");
      exit(1);
    }
  *input_suffix='\0';
  input_suffix++;

  if ((dir=opendir("."))==NULL)
    {
      perror("get_file_list: opendir");
      exit(1);
    }

  *num_input_files=0;
  *input_file_nums=NULL;
  
  while ((dirent=readdir(dir))!=NULL)
    {
      if (!strncmp(dirent->d_name, input_prefix, strlen(input_prefix)))
        {
          j=0;
          for (i=0;i<num_digits;i++)
            if (isdigit(num_string[j]=dirent->d_name[strlen(input_prefix)+i]))
              j++;
	  num_string[j]='\0';

          /* Check if it's valid .. */
          if (j==num_digits &&
              !strcmp(input_suffix,
                      dirent->d_name+strlen(input_prefix)+num_digits+1))
            {
              (*num_input_files)++;
              *input_file_nums=realloc(*input_file_nums,
				       sizeof(int)*(*num_input_files+1));
              (*input_file_nums)[*num_input_files-1]=atoi(num_string);
            }
        }
    }
  closedir(dir);
}


int
main(int argc, char ** argv)
{
  int num_digits, num_files, i;
  char old_name[1024];
  char new_name[1024];
  char format_string[64];
  int * file_num_list;

  if (argc<3) usage(*argv);

  if ((num_digits=atoi(argv[2]))<1)
    {
      fprintf(stderr, "%s: num_digits must be greater than zero.\n", *argv);
      usage(*argv);
    }

  fprintf(stderr, "%s: Scanning directory for matching files...", *argv);
  fflush(stderr);

  get_file_list(argv[1], &file_num_list, &num_files, num_digits);

  if (!num_files)
    {
      fprintf(stderr, " No matching files found.\n");
      exit(1);
    }

  fprintf(stderr, " Found %d matching files.\n", num_files);
  fprintf(stderr, "%s: Sorting file names..\n", *argv);
  qsort(file_num_list, num_files, sizeof(int), &my_compare_function);
  sprintf(format_string, "%%s%%%02dd.%%s", num_digits);
  printf("format_string: %s\n", format_string);
  for (i=0;i<num_files;i++)
    {
      sprintf(old_name, format_string, input_prefix, file_num_list[i],
	      input_suffix);
      sprintf(new_name, format_string, input_prefix, i, input_suffix);
#ifdef VERBOSE
      fprintf(stderr, "%s: Renaming %s to %s...\n", *argv, old_name,
	      new_name);
#endif
      rename(old_name, new_name);
    }
  exit(0);
}

