BRT - Bulk Renaming Tool
Publicado por Pedro Fernandes (última atualização em 25/03/2024)
[ Hits: 1.475 ]
Homepage: https://github.com/PedroF37
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!
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
Programa para inversão de colunas
Justificador de texto em 80 colunas
Copia uma linha selecionada para um arquivo secundário
Atenção a quem posta conteúdo de dicas, scripts e tal (6)
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
O mínimo que você precisa saber sobre o terminal (parte 2)
O mínimo que você precisa saber sobre o terminal (parte 1)
Como iniciar uma máquina virtual do VirtualBox automaticamente no boot do LUbuntu 18 LTS
Mudar o gerenciador de login (GDM para SDDM e vice-versa) - parte 2
Como deixar as abas do Firefox mais fininhas
Mudar o gerenciador de login (GDM para SDDM)
"Tentando" fazer com que programas rodem no Wayland e no X11
Adaptador USB WiFi5 DualBand 1300 WiFI AC1300 (Realtek Semiconductor C... (1)
Como baixar os drivers de áudio no linux mint? (2)
Erro Problema com instalação de Endian Firewall em novo computador. pl... (2)