CSC352 Walking a 2-Level Directory in C

From dftwiki3
Revision as of 09:14, 21 November 2013 by Thiebaut (talk | contribs) (Create fake files)
Jump to: navigation, search

--D. Thiebaut (talk) 07:28, 21 November 2013 (EST)



Create a test structure

Directory structure

  • Using bash, from the command line, create a similar structure:
for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f ; do 
  for j in 0 1 2 3 4 5 6 7 8 9 a b c d e f ; do 
      echo ${i}${j}; 
      mkdir -p ${i}/${i}${j}  
  done
done

Create fake files

  • create files using the "touch" command
for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f ; do 
    for j in 0 1 2 3 4 5 6 7 8 9 a b c d e f ; do 
        echo ${i}${j}; 
        touch ${i}/${i}${j}/image_${i}${j}.jpg  
        touch ${i}/${i}${j}/image_${j}${i}.png   
    done  
done

Source


// walk2.c
// D. Thiebaut
// Taken originally from http://stackoverflow.com/questions/612097/
//                      how-can-i-get-a-list-of-files-in-a-directory-using-c-or-c
// and adapted to fit the current problem.
//
// This program assumes that there is a directory structure containing data files
// The directory structure has this form:
// en/0
// en/0/00
// en/0/01
// en/0/02
// ...
// en/0/0f
// en/1/10
// en/1/12
// ...
// en/1/1f
// en/2/20
// ...
// en/f/ff
// 
// This program provides a function called nextFile() that will start by reading
// the directory en/0/00 and return all the files in it, ONE AT A TIME.  
// Then it will move on to en/0/01, and return all the files in it, ONE AT A TIME.
// And so on until it has read the final file in en/f/ff, when it will return NULL
// instead of a file name.
// 
// Testing: bash commands to create a directory structure along with 2 dummy image
// files in each directory:
//
// cd ./en
// for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f ; do
//   for j in 0 1 2 3 4 5 6 7 8 9 a b c d e f ; do  
//       echo ${i}${j}
//       mkdir -p ${i}/${i}${j}  
//       touch ${i}/${i}${j}/image_${i}${j}.jpg 
//       touch ${i}/${i}${j}/image_${j}${i}.png 
//   done 
// done 
//

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

char *path;

char* nextPath() {
  int len = strlen( path );

  //--- if last char not 'f', simply increment it ---
  if ( path[ len-1 ]<'9' ) {
    path[len-1] += 1;
    return path;
  }
  else if (path[len-1]=='9' ) {
    path[len-1] = 'a';
    return path;
  }
  else if (path[len-1]<'f' ) {
    path[len-1] += 1;
    return path;
  }


  //--- increment other digit ---
  path[len-1] = '0';
  if ( path[len-2] <'9' ) {
    path[len-2] += 1;
    path[len-4] = path[len-2];
    return path;
  }
  else if ( path[len-2]=='9' ) {
    path[len-2] = 'a';
    path[len-4] = path[len-2];
    return path;
  }
  else if ( path[len-2]<'f' ) {
    path[len-2] += 1;
    path[len-4] = path[len-2];
    return path;
  }

  //--- if we had reached the end, return null ---
  path[len-1] = '0';
  path[len-2] = '0';
  path[len-4] = '0';
  return NULL;
}

int firstTime = 1;
DIR *dir;
char *nextFile() {
  //--- if first time, open dir ---
  if ( firstTime ) {
    firstTime = 0;
    dir = opendir ( path );
    if ( dir == NULL) 
      return NULL;
  }

  //--- if we've read everything already, return NULL ---
  if ( path==NULL )
    return NULL;

  //--- get next file ---
  struct dirent *ent;
  ent = readdir (dir);
  if ( ent == NULL ) {
    closedir( dir );
    path = nextPath();
    firstTime = 1;
    return nextFile();
  }

  //--- skip . and .. files ---
  if ( strcmp( ent->d_name, "." )== 0
       || strcmp( ent->d_name, ".." )== 0 )
    return nextFile();

  //--- return file ---
  return ent->d_name;
}

int main( int argc, char **argv) {

  int count = 0;
  char *fileName = NULL;
  path = (char *) malloc( sizeof( "en/0/00" ) * sizeof( char ) );
  strcpy( path, "en/0/00" );

  if ( argc < 2 ) {
    fprintf( stderr, "Syntax: ./walk path" );
    exit( 0 );
  }

  while ( (fileName = nextFile()) != NULL ) {
    //if ( strcmp( fileName, "." )==0 
    //     || strcmp( fileName, ".." )==0 )
    //  continue;
    printf( "%s\n", fileName );
  }
  
}