BRT - Bulk Renaming Tool

Publicado por Pedro Fernandes (última atualização em 25/03/2024)

[ Hits: 1.517 ]

Homepage: https://github.com/PedroF37

Download BRT.tar.gz




Projeto em C de um utilitário de renomeação em massa de arquivos pela linha de comando. Pode inserir antes do nome, adicionar depois de string alvo no nome, substituir antigo por novo e deletar sub string em nome de arquivo.

Programa usa recursividade, então varre o diretório alvo e os seus subdiretórios e renomeia todos os arquivos alvo. Programa também permite executar todas as operações filtrando pela extensão do arquivo, então, as operações são executadas nos nomes de arquivos que correspondem com o alvo, mas apenas os que têm a extensão indicada.

Códigos fontes, um Makefile e restantes instruções, assim como exemplos de uso estão no repositório do projeto:
https://github.com/PedroF37/BRT

Grato!

  



Esconder código-fonte

Arquivos brt.c e brt.h:

#include "brt.h"
#include "helper.h"
#include "args.h"


#define ARG_MIN 5
#define ARG_MAX 7


int main(int argc, char **argv)
{
    if (argc < ARG_MIN || argc > ARG_MAX)
    {
        print_usage();
        return(EXIT_FAILURE);
    }

    if (!is_valid_directory(*(argv + 1)))
    {
        fprintf(stderr, "Diretório %s é inválido ou"
            " você não tem permissões\n", *(argv + 1));
        return(EXIT_FAILURE);
    }

    argv++;
    map_operation(argc - 3, argv);
    return(EXIT_SUCCESS);
}


#ifndef _BRT_H
#define _BRT_H


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <libgen.h>

#include <fileutils.h>
#include <dirutils.h>
#include <strutils.h>


#endif


/****************************************************************************************************************************************/


Arquivos args.c e args.h


#include "brt.h"
#include "args.h"
#include "helper.h"


void number_args(int argc, int args)
{
    if (argc != args)
    {
        print_usage();
        exit(EXIT_FAILURE);
    }

    return;
}


void map_operation(int argc, char **argv)
{
    Operation operation;
    char *directory = *argv++;
    char *operation_str = *argv++;
    remove_last_char(directory, '/');

    if (strcmp(operation_str, "-a") == 0 ||
        strcmp(operation_str, "--add") == 0)
    {
        number_args(argc, 2);
        operation = ADD;
    }
    else if (strcmp(operation_str, "-i") == 0 ||
        strcmp(operation_str, "--insert") == 0)
    {
        number_args(argc, 2);
        operation = INSERT;
    }
    else if (strcmp(operation_str, "-ae") == 0 ||
        strcmp(operation_str, "--add-ext") == 0)
    {
        number_args(argc, 3);
        operation = ADD_EXT;
    }
    else if (strcmp(operation_str, "-ie") == 0 ||
        strcmp(operation_str, "--insert-ext") == 0)
    {
        number_args(argc, 3);
        operation = INSERT_EXT;
    }
    else if (strcmp(operation_str, "-r") == 0 ||
        strcmp(operation_str, "--replace") == 0)
    {
        number_args(argc, 3);
        operation = REPLACE;
    }
    else if (strcmp(operation_str, "-re") == 0 ||
        strcmp(operation_str, "--replace-ext") == 0)
    {
        number_args(argc, 4);
        operation = REPLACE_EXT;
    }
    else if (strcmp(operation_str, "-d") == 0 ||
        strcmp(operation_str, "--delete") == 0)
    {
        number_args(argc, 2);
        operation = DELETE;
    }
    else if (strcmp(operation_str, "-de") == 0 ||
        strcmp(operation_str, "--delete-ext") == 0)
    {
        number_args(argc, 3);
        operation = DELETE_EXT;
    }
    else
    {
        print_usage();
        exit(EXIT_FAILURE);
    }

    search_directory(operation, directory, argv);
}


#ifndef _ARGS_H
#define _ARGS_H


/* A operação de renomeação */
typedef enum OperationType
{
    ADD, INSERT, ADD_EXT,
    INSERT_EXT, REPLACE,
    REPLACE_EXT, DELETE,
    DELETE_EXT
}
Operation;


/* Cuida de garantir o número certo de argumentos */
void number_args(int argc, int args);


/* Cuida de mapear a operação a ser executada */
void map_operation(int argc, char **argv);


#endif


/*****************************************************************************************************************************/


Arquivos helper.c e helper.h


#include "brt.h"
#include "helper.h"


void print_usage()
{
    printf("\nBulk Renaming Tool - Renomeação em Massa de Arquivos\n\n"
           "Uso: brt Diretório OPÇÃO ALVO\n\n"
           "OPÇÕES:\n"
           "  -a, --add            Alvo Adicionar\n"
           "  -i, --insert         Alvo Inserir\n"
           "  -ae, --add-ext       Alvo Adicionar Extensão\n"
           "  -ie, --insert-ext    Alvo Inserir Extensão\n"
           "  -r, --replace        Alvo Antigo Novo\n"
           "  -re, --replace-ext   Alvo Antigo Novo Extensão\n"
           "  -d, --delete         Alvo Deletar\n"
           "  -de, --delete-ext    Alvo Deletar Extensão\n\n"
           "Todas as operações executadas são feitas usando recursão no diretório alvo\n\n"
           "Exemplos:\n\n"
           "  $ brt /home/usuario/Documentos -a curriculum -profissional\n"
           "     Adiciona '-profissional' depois de 'curriculum', a todos os arquivos em Documentos com 'curriculum' no nome\n"
           "  $ brt ~/Imagens -i Férias-de-Verão Minhas-\n"
           "     Insere antes de 'Férias-de-Verão' 'Minhas-' em todos os arquivos em Imagens com 'Férias-de-Verão' no nome\n"
           "  $ brt ~/Videos --add-ext Aniversário -2023 mp4\n"
           "     Adiciona '-2023' depois de 'Aniversário' em todos os arquivos em Videos com 'Aniversário' no nome, mas apenas os que têm a extensão 'mp4'\n"
           "  $ brt ~/Videos -ie Aniversário Minha-Festa-de- mkv\n"
           "     Insere antes de 'Aniversário' 'Minha-Festa-de-' em todos os arquivos em Videos com 'Aniversário' no nome, mas apenas os que têm a extensão 'mkv'\n"
           "  $ brt /home/usuario/Imagens --replace Natal _2021 _2022\n"
           "     Substitui em Imagens '_2021' por '_2022' em todos os arquivos com 'Natal' no nome\n"
           "  $ brt ~/Imagens -re Natal _2021 _2022 jpg\n"
           "     Sustitui em Imagens '_2021' por '_2022' em todos os arquivos com 'Natal' no nome, mas apenas os que têm a extensão 'jpg'\n"
           "  $ brt ~/Documentos -d curriculum -profissional\n"
           "     Deleta em Documentos '-profissional' em todos os arquivos com 'curriculum' no nome\n"
           "  $ brt ~/Documentos --delete-ext curriculum -profissional docx\n"
           "     Deleta em Documentos '-profissional' em todos os arquivos com 'curriculum' no nome mas apenas os que têm a extensão 'docx'\n\n");
    return;
}


bool is_renamed(char *pathname, char *new_name)
{
    if (rename(pathname, new_name) != 0)
    {
        return(false);
    }

    return(true);
}


bool has_same_extension(char *pathname, char *extension)
{
    char *ext;
    if ((ext = has_extension(pathname)) == NULL)
    {
        return(false);
    }

    if (strcmp(ext, extension) != 0)
    {
        return(false);
    }

    return(true);
}


char *remove_dot_from_extension(char *extension)
{
    char *new_ext;
    if ((new_ext = strrchr(extension, '.')) != NULL)
    {
        return(new_ext + 1);
    }

    return(extension);
}


Result call_operation(Operation operation,
    char *pathname, char **argv)
{
    Result result;
    char *ext = NULL;
    switch (operation)
    {
        case ADD:
            result = add_in_filename(pathname,
                *argv, *(argv + 1));
            break;

        case INSERT:
            result = insert_in_filename(pathname,
                *(argv + 1));
            break;

        case ADD_EXT:
            ext = remove_dot_from_extension(*(argv + 2));
            result = add_in_filename_ext(pathname,
                *argv, *(argv + 1), ext);
            break;

        case INSERT_EXT:
            ext = remove_dot_from_extension(*(argv + 2));
            result = insert_in_filename_ext(pathname,
                *(argv + 1) ,ext);
            break;

        case REPLACE:
            result = replace_in_filename(pathname,
                *(argv + 1), *(argv + 2));
            break;

        case REPLACE_EXT:
            ext = remove_dot_from_extension(*(argv + 3));
            result = replace_in_filename_ext(pathname,
                *(argv + 1), *(argv + 2), ext);
            break;

        case DELETE:
            result = delete_in_filename(pathname,
                *(argv + 1));
            break;

        case DELETE_EXT:
            ext = remove_dot_from_extension(*(argv + 2));
            result = delete_in_filename_ext(pathname,
                *(argv + 1), ext);
            break;
    }

    return(result);
}


void search_directory(Operation operation,
    char *directory, char **argv)
{
    DIR *dhandle;
    if ((dhandle = opendir(directory)) == NULL)
    {
        fprintf(stderr, "Erro abrindo %s\n", directory);
        closedir(dhandle);
        exit(EXIT_FAILURE);
    }

    struct dirent *entry;
    Result result;
    while ((entry = readdir(dhandle)) != NULL)
    {
        char *fullpath;
        if ((fullpath = create_pathname(directory,
            entry->d_name)) == NULL)
        {
            fprintf(stderr, "Erro criando"
                " caminho para %s\n", entry->d_name);
            closedir(dhandle);
            exit(EXIT_FAILURE);
        }

        if (is_dot_directory(entry->d_name) ||
            is_simlink(fullpath))
        {
            continue;
        }

        if (is_directory(fullpath))
        {
            remove_last_char(fullpath, '/');
            search_directory(operation, fullpath, argv);
        }

        if (is_equal_name(basename(fullpath), *argv) == false)
        {
            continue;
        }

        if ((result = call_operation(operation,
            fullpath, argv)) != SUCCESS)
        {
            if (result == CONTINUE)
            {
                continue;
            }
            else
            {
                closedir(dhandle);
                exit(EXIT_FAILURE);
            }
        }

        free(fullpath);
    }

    closedir(dhandle);
}


#ifndef _HELPER_H
#define _HELPER_H


#include "operations.h"
#include "args.h"

/* Cuida de mostrar como usar o programa */
void print_usage();


/* Renomeia e retorna true ou false
 * para se foi ou não renomeado */
bool is_renamed(char *pathname, char *new_name);


/* Cuida de verificar que se tem extensão e se são iguais */
bool has_same_extension(char *pathname, char *extension);


/* Cuida de remover o . de ".pdf", etc, caso tenha digitado . */
char *remove_dot_from_extension(char *extension);


/* Cuida de chamar a operação apropriada */
Result call_operation(Operation operation,
    char *pathname, char **argv);


/* Cuida de varrer o diretório alvo recursivamente */
void search_directory(Operation operation,
    char *directory, char **argv);

#endif


/**************************************************************************************************************/


Arquivos operations.c e operations.h


#include "brt.h"
#include "operations.h"
#include "helper.h"


Result add_in_filename(char *pathname,
    char *target, char *addition)
{
    char *new_name;
    if ((new_name = str_insert(pathname,
        target, addition)) == NULL)
    {
        return(FAILURE);
    }

    if (is_renamed(pathname,
        new_name) == false)
    {
        free(new_name);
        return(FAILURE);
    }

    printf("%s -->> %s\n", pathname, new_name);

    free(new_name);
    return(SUCCESS);
}


Result insert_in_filename(char *pathname, char *insert)
{
    char *new_name;
    if ((new_name = insert_in_beginning(basename(
        pathname), insert)) == NULL)
    {
        return(FAILURE);
    }

    char *pathname_copy = duplicate(pathname);
    if (pathname_copy == NULL)
    {
        free(new_name);
        return(FAILURE);
    }

    char *full_new_name;
    if ((full_new_name = create_pathname(
        dirname(pathname_copy), new_name)) == NULL)
    {
        free(pathname_copy);
        free(new_name);
        return(FAILURE);
    }

    if (is_renamed(pathname,
        full_new_name) == false)
    {
        free(pathname_copy);
        free(full_new_name);
        free(new_name);
        return(FAILURE);
    }

    printf("%s -->> %s\n", pathname, full_new_name);

    free(pathname_copy);
    free(full_new_name);
    free(new_name);
    return(SUCCESS);
}


Result add_in_filename_ext(char *pathname,
    char *target, char *addition, char *extension)
{
    if (has_same_extension(pathname,
        extension) == false)
    {
        return(CONTINUE);
    }

    char *new_name;
    if ((new_name = str_insert(pathname,
        target, addition)) == NULL)
    {
        return(FAILURE);
    }

    if (is_renamed(pathname, new_name) == false)
    {
        free(new_name);
        return(FAILURE);
    }

    printf("%s -->> %s\n", pathname, new_name);

    free(new_name);
    return(SUCCESS);
}


Result insert_in_filename_ext(char *pathname,
    char *insert, char *extension)
{
    if (has_same_extension(pathname,
        extension) == false)
    {
        return(CONTINUE);
    }

    char *new_name;
    if ((new_name = insert_in_beginning(
        basename(pathname), insert)) == NULL)
    {
        return(FAILURE);
    }

    char *pathname_copy = duplicate(pathname);
    if (pathname_copy == NULL)
    {
        free(new_name);
        return(FAILURE);
    }

    char *full_new_name;
    if ((full_new_name = create_pathname(
        dirname(pathname_copy), new_name)) == NULL)
    {
        free(pathname_copy);
        free(new_name);
        return(FAILURE);
    }

    if (is_renamed(pathname,
        full_new_name) == false)
    {
        free(pathname_copy);
        free(full_new_name);
        free(new_name);
        return(FAILURE);
    }

    printf("%s -->> %s\n", pathname, full_new_name);

    free(pathname_copy);
    free(full_new_name);
    free(new_name);
    return(SUCCESS);
}


Result replace_in_filename(char *pathname,
    char *old_str, char *new_str)
{
    char *new_name;
    if ((new_name = str_replace(pathname,
        old_str, new_str)) == NULL)
    {
        return(FAILURE);
    }

    if (is_renamed(pathname, new_name) == false)
    {
        free(new_name);
        return(FAILURE);
    }

    printf("%s -->> %s\n", pathname, new_name);

    free(new_name);
    return(SUCCESS);
}


Result replace_in_filename_ext(char *pathname,
    char *old_str, char *new_str, char *extension)
{
    if (has_same_extension(pathname,
        extension) == false)
    {
        return(CONTINUE);
    }

    char *new_name;
    if ((new_name = str_replace(pathname,
        old_str, new_str)) == NULL)
    {
        return(FAILURE);
    }

    if (is_renamed(pathname, new_name) == false)
    {
        free(new_name);
        return(FAILURE);
    }

    printf("%s -->> %s\n", pathname, new_name);

    free(new_name);
    return(SUCCESS);
}


Result delete_in_filename(char *pathname, char *to_delete)
{
    char *new_name;
    if ((new_name = str_remove(pathname,
        to_delete)) == NULL)
    {
        return(FAILURE);
    }

    if (is_renamed(pathname, new_name) == false)
    {
        free(new_name);
        return(FAILURE);
    }

    printf("%s -->> %s\n", pathname, new_name);

    free(new_name);
    return(SUCCESS);
}


Result delete_in_filename_ext(char *pathname,
    char *to_delete, char *extension)
{
   if (has_same_extension(pathname,
        extension) == false)
   {
       return(CONTINUE);
   }

    char *new_name;
    if ((new_name = str_remove(pathname,
        to_delete)) == NULL)
    {
        return(FAILURE);
    }

    if (is_renamed(pathname, new_name) == false)
    {
        free(new_name);
        return(FAILURE);
    }

    printf("%s -->> %s\n", pathname, new_name);

    free(new_name);
    return(SUCCESS);
}


#ifndef _OPERATIONS_H
#define _OPERATIONS_H


/* O resultado da operação escolhida */
typedef enum OperationResult
{
    SUCCESS, CONTINUE, FAILURE
}
Result;


/* Cuida de adicionar no nome depois de target */
Result add_in_filename(char *pathname, char *target, char *addition);


/* Cuida de inserir no nome antes de target */
Result insert_in_filename(char *pathname, char *insert);


/* Cuida de adicionar no nome depois de target, filtrando por extensão*/
Result add_in_filename_ext(char *pathname, char *target,
    char *addition, char *extension);


/* Cuida de inserir no nome antes de target, filtrando por extensão*/
Result insert_in_filename_ext(char *pathname,
    char *insert, char *extension);


/* Cuida de substituir old_str por new_str nos
 * arquivos com target no nome */
Result replace_in_filename(char *pathname,
    char *old_str, char *new_str);


/* Cuida de substituir old_str por new_str nos
 * arquivos com target no nome, filtrando por extensão*/
Result replace_in_filename_ext(char *pathname,
    char *old_str, char *new_str, char *extension);


/* Cuida de deletar to_delete nos arquivos com target no nome */
Result delete_in_filename(char *pathname, char *to_delete);


/* Cuida de deletar to_delete nos arquivos com
 * target no nome, filtrando por extensão*/
Result delete_in_filename_ext(char *pathname,
    char *to_delete, char *extension);


#endif

Scripts recomendados

Super Truco

Ler config

Pilhas C/C++ - Pares e ímpares

Programinha que busca arquivos

codificador de texto


  

Comentários
[1] Comentário enviado por maurixnovatrento em 23/06/2024 - 17:26h

Muito bom, foi bem esforçado.
______________________________________________________________________
Inscreva-se no meu Canal: https://www.youtube.com/@LinuxDicasPro
Repositório GitHub do Canal: https://github.com/LinuxDicasPro
Grupo do Telegram: https://t.me/LinuxDicasPro
Meu GitHub Pessoal: https://github.com/mxnt10


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts