Skip to main content
edited tags
Link
Became Hot Network Question
Improved the title
Link

C remove Remove all text files with non-usUS-asciiASCII text encoding from current folder on Linux

Source Link

C remove all text files with non-us-ascii text encoding from current folder on Linux

/* let's compile using: gcc main.c -Wall -Wextra --pedantic --std=c2x -D_GNU_SOURCE -Ofast -march=corei7 -mtune=corei7 */
/* Linux headers begin */
#include <dirent.h> 
#include <sys/stat.h> 
#include <unistd.h>
/* Linux headers end */
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define ALLOCATION_ATTEMPT_LIMIT 4
#define SUCCESS 0
#define FAIL -1

char * concat_file_path(const char * directory, const char * file_name)
{
    const char * separator = "/";
    char * result = NULL;
    size_t directory_length = strlen(directory);
    size_t file_name_length = strlen(file_name);
    size_t separator_length = strlen(separator);
    char count  = 0;
 
    while (((result = malloc(sizeof(char) * (directory_length + separator_length + file_name_length + 1))) == NULL) && (++count < ALLOCATION_ATTEMPT_LIMIT))
        sleep(1);

    if (result == NULL)
    {
        perror("Error: memory allocation failed.");
    
        exit(EXIT_FAILURE);
    }

    memcpy(result, directory, directory_length);
    memcpy(result + directory_length, separator, separator_length);
    memcpy(result + directory_length + separator_length, file_name, file_name_length + 1);

   return result;   
}

void close_directory(DIR * directory_pointer)
{
    if (closedir(directory_pointer) == 0)
    {
        puts("Directory was closed.");
    }
    else
        perror("Error: closing directory failed.");
}

DIR * open_directory(const char * directory_path)
{
    DIR * directory_pointer = opendir(directory_path);

    if (directory_pointer == NULL)
    {
        perror("Error: directory stream is NULL.");
    
        exit(EXIT_FAILURE); 
    }

    return directory_pointer;
}

char check_for_non_ascii(FILE * text_file_pointer)
{
    char current = fgetc (text_file_pointer);

    if (current == EOF)
        return FAIL;

    do
    {
        if (isascii(current) == 0)      
            return FAIL;
    }
    while ((current = fgetc (text_file_pointer)) != EOF);

    return SUCCESS;
}

void remove_if_non_us_ascii(char * full_path)
{
    FILE * text_file_pointer = fopen(full_path, "r");

    if (text_file_pointer == NULL)
    {
        perror("Error: file opening error.");
    
        exit(EXIT_FAILURE);
    }

    if (check_for_non_ascii(text_file_pointer) == 0)
    {
        fclose(text_file_pointer);
    
    
        if (remove(full_path) == 0)
        {
            puts("File removed.");
        }
        else
        {
            printf("Occured an error on removing a file on the path: %s", full_path);
        }
    }
    else
        fclose(text_file_pointer);
}

void perform_if_regular_file(DIR * directory_pointer, char * full_path)
{
    struct stat stat_buffer;

    if (lstat(full_path, &stat_buffer) == 0) 
    {       
        if ((stat_buffer.st_mode & S_IFMT) == S_IFREG) 
        {
            remove_if_non_us_ascii(full_path);
        }
    }
    else
    {
        perror("Error: getting file information failed.");
    
        close_directory(directory_pointer);
    
        exit(EXIT_FAILURE);
    }
}

void main_loop(DIR * directory_pointer, const char * directory_path)
{   
    struct dirent * directory_entry_struct = NULL;
    char * full_path = NULL;

    while ((directory_entry_struct = readdir (directory_pointer)) != NULL)
    {
        full_path = concat_file_path(directory_path, directory_entry_struct->d_name);       
    
        perform_if_regular_file(directory_pointer, full_path);
    }
}

int main (void)
{
    const char * directory_path = ".";
    DIR * directory_pointer = open_directory(directory_path);   
    errno = 0;   

    main_loop(directory_pointer, directory_path);

    if (errno != 0)
    {
        perror("Error: reading directory entry failed.");
    
        close_directory(directory_pointer);
        
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

I am new to C. Please, give an advice on reliability of program, programming style and performance. You have to put program executable into a folder containing text files in any encoding on Linux machine. After running it you could have only US ASCII text files in the folder. I have tested this code on a 11 GiB storage.