← Back to team overview

sslug-teknik team mailing list archive

Re: Prefix oversigt

 



On Sun, 6 Aug 2006, Jens Bang wrote:

Jeg har en samling filer der i nogle tilfælde deler prefix. Der kan f.eks.
være 50 filer der starter med 2006-04-05_ og 100 der starter med 2006-05-24_.

Hvordan får jeg en oversigt over hvilke prefix'er der er?

Herunder er der et lille stykke skole C som gør arbejdet. OK, den er så velkommenteret at jeg nok får 03 ;-) Du gemmer koden i en fil med navnet prefixfiles.c og oversætter med gcc -o prefixfiles prefixfiles.c
Derefter fjerner du debuginformationen med strip prefixfiles.
syntaks er prefixfiles [katalog]

Opgaven kan selvfølgelig også gøres elegant i perl, pascal eller smalltalk - lad os se.

Mvh. Bo

[prefixfiles.c]--------------------klip-------------------------

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

typedef struct
{
  char *name;
  int number;
  long size;
} PREFIXFILE;

PREFIXFILE *files = NULL;
int count = 0;
int capacity = 0;

int addmatch(char *name, long size)
{
  int r;

  if (capacity == count)
    {
      capacity += 100;
      files = (PREFIXFILE *)realloc(files, capacity * sizeof(PREFIXFILE));
      if (!files) return -1;
    }

  for (r = 0; r < count; r++)
    {
       if (strcmp((files + r)->name, name)  == 0)
         {
	   (files + r)->number++;
	   (files + r)->size += size;
	   return count;
	 }
    }

  (files + count)->name = strdup(name);
  (files + count)->number = 1;
  (files + count)->size = size;
  count++;

  return count;
}

int scan(char *directory)
{
  DIR *dir;
  struct dirent *entry;
  struct stat filestat;
  char *workspace;
  char *eow;
  char *p;
  int value = 0;

  dir = opendir(directory);
  if (!dir) return -2;

  value = strlen(directory) + 260;
  workspace = (char *)malloc(value);
  if (!workspace) return -1;
  strcpy(workspace, directory);
  eow = workspace;
  while (*eow) eow++;
  eow--;
  if (*eow != '/')
    {
      eow++;
      *eow = '/';
    }
  eow++;

  entry = readdir(dir);
  while (entry)
    {
      *eow = (char)NULL;
      strcat(workspace, entry->d_name);
      stat(workspace, &filestat);
      if (S_ISREG(filestat.st_mode))
        {
          p = entry->d_name;

          while (*p != (char)NULL && *p != '.')
	    {
	      if (*p == '_')
	        {
		  *p = (char)NULL;
		  value = addmatch(entry->d_name, filestat.st_size);
		  if (value < 0) return value;
		  break;
		}
	      p++;
	    }
        }
      entry = readdir(dir);
    }

  free(workspace);
  closedir(dir);
return value; }

void report(void)
{
  int r;
  int total = 0;
  long totalsize = 0;

  for (r = 0; r < count; r++)
    {
      total += (files + r)->number;
      totalsize += (files + r)->size;
      fprintf(stdout, "%u files\t%16lu bytes\t%s\n",
                (files + r)->number,(files + r)->size, (files + r)->name );
    }

  fprintf(stdout, "\ntotal %u unique prefix, %u files, %lu bytes\n",
                                                    count, total, totalsize);
}

int main(int argc, char *argv[])
{
  char buffer[1024];
  char *p;
  int retval;

  p = buffer;
  *p = (char)NULL;

  if (argc < 2) strcat(p, ".");
  else if (*argv[1] == '/' || *argv[1] == '.') strcat(p, argv[1]);
  else
    {
      strcat(p, "./");
      strcat(p, argv[1]);
    }

  retval = scan(p);

  if (retval == -2) fprintf(stderr, "%s is not a directory.\n", p);
  if (retval == -1) fprintf(stderr, "Memory allocation error.\n");
  if (retval == 0) fprintf(stdout, "No files with prefix found.\n");
  if (retval > 0) report();

  return retval;
}

References