NSRover
NSRover

Reputation: 978

How do I loop through all files in a folder using C?

I want to remove a particular substring from all the file names in a directory:

-- like 'XYZ.com' from 'Futurama s1e20 - [XYZ.com].avi' --

So basically I need to provide the method with a desired substring, and it has to loop through all file names and compare.

I cant figure out how to loop through all files in a folder using C.

Upvotes: 14

Views: 59383

Answers (7)

Ted Klein Bergman
Ted Klein Bergman

Reputation: 9766

You can use dirent.h for POSIX systems.

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

// POSIX
#include <dirent.h>


#define MAX_FILE_NAME_SIZE 256


int read_directories(const char* path) {
    DIR* directory = opendir(path);
    if (directory == NULL) {
        fprintf(stderr, "Can't open %s\n", path);
        return EXIT_FAILURE;
    }

    struct dirent* entry = NULL;
    while ((entry = readdir(directory)) != NULL) {
        char full_name[MAX_FILE_NAME_SIZE] = { 0 };
        snprintf(full_name, MAX_FILE_NAME_SIZE, "%s/%s", path, entry->d_name);

        if (entry->d_type == DT_DIR) {
            // Recurse unless the directory is the current (".") or parent ("..") directory.
            if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
                printf("'%s' is a directory\n", full_name);
                read_directories(full_name);
            }
        } else {
            printf("'%s' is a file\n", full_name);
        }
    }

    closedir(directory);
    return EXIT_SUCCESS;
}


int main(int argc, const char* const argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Must provide at most one path\n");
        fprintf(stderr, "Usage: %s <directory>\n", argv[0]);
        return EXIT_FAILURE;
    }

    const char* path = argv[1];
    return read_directories(path);
}

Example running the executable in the terminal:

cc main.c -o main && ./main .

Upvotes: 2

justc
justc

Reputation:

You may use FTS(3) to loop through all files in a folder using C:

http://keramida.wordpress.com/2009/07/05/fts3-or-avoiding-to-reinvent-the-wheel/

Upvotes: 6

user140327
user140327

Reputation:

I know this answer will get me down-voted, but your problem is perfect for a shell script, (or .cmd script), a PHP script, or PERL script. Doing it in C is more work than the problem is worth.

Upvotes: 3

Norman Ramsey
Norman Ramsey

Reputation: 202655

fts has a nice interface, but it's 4.4BSD and is not portable. (I recently got bitten in the rear by some software with an inherent dependency on fts.) opendir and readdir are less fun but are POSIX standards and are portable.

Upvotes: 1

sud03r
sud03r

Reputation: 19779

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

int main(int argc, char** argv)
{
 struct dirent *dp;
 DIR *dfd;

 char *dir ;
 dir = argv[1] ;

 if ( argc == 1 )
 {
  printf("Usage: %s dirname\n",argv[0]);
  return 0;
 }

 if ((dfd = opendir(dir)) == NULL)
 {
  fprintf(stderr, "Can't open %s\n", dir);
  return 0;
 }

 char filename_qfd[100] ;
 char new_name_qfd[100] ;

 while ((dp = readdir(dfd)) != NULL)
 {
  struct stat stbuf ;
  sprintf( filename_qfd , "%s/%s",dir,dp->d_name) ;
  if( stat(filename_qfd,&stbuf ) == -1 )
  {
   printf("Unable to stat file: %s\n",filename_qfd) ;
   continue ;
  }

  if ( ( stbuf.st_mode & S_IFMT ) == S_IFDIR )
  {
   continue;
   // Skip directories
  }
  else
  {
   char* new_name = get_new_name( dp->d_name ) ;// returns the new string
                                                   // after removing reqd part
   sprintf(new_name_qfd,"%s/%s",dir,new_name) ;
   rename( filename_qfd , new_name_qfd ) ;
  }
 }
}

Although I would personally prefer a script to do this job like


#!/bin/bash -f
dir=$1
for file in `ls $dir`
do
 if [ -f $dir/$file ];then
  new_name=`echo "$file" | sed s:to_change::g`
  mv $dir/$file $dir/$new_name
 fi
done

Upvotes: 16

msh
msh

Reputation: 567

The key functions are _findfirst, _findnext and _findclose

struct _finddata_t file_info;
char discard[] = "XYZ.com";
char dir[256] = "c:\\folder\\";
char old_path[256];
char new_path[256];
intptr_t handle = 0;

memset(&file_info,0,sizeof(file_info));

strcpy(old_path,dir);
strcat(old_path,"*.avi");

handle = _findfirst(old_path,&file_info);
if (handle != -1)
{
    do
    {
        char *new_name = NULL;
        char *found = NULL;
        new_name = strdup(file_info.name);
        while ((found = strstr(new_name,discard)) != 0)
        {
            int pos = found - new_name;
            char* temp = (char*)malloc(strlen(new_name));
            char* remain = found+strlen(discard);
            temp[pos] = '\0';
            memcpy(temp,new_name,pos);
            strcat(temp+pos,remain);
            memcpy(new_name,temp,strlen(new_name));
            free(temp);
        }
        strcpy(old_path,dir);
        strcat(old_path,file_info.name);
        strcpy(new_path,dir);
        strcat(new_path,new_name);
        rename(old_path,new_path);
        free(new_name);
    }while(_findnext(handle,&file_info) != -1);
}
    _findclose(handle);

Upvotes: 2

mouviciel
mouviciel

Reputation: 67879

Take a look at dirent.h.

Upvotes: 2

Related Questions