BRT - Bulk Renaming Tool
Publicado por Pedro Fernandes (última atualização em 25/03/2024)
[ Hits: 1.540 ]
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
Manipulação de registros em arquivos utilizando índices
Gerenciamento de alunos com dados armazenados em arquivo
Enviar mensagem ao usuário trabalhando com as opções do php.ini
Meu Fork do Plugin de Integração do CVS para o KDevelop
Compartilhando a tela do Computador no Celular via Deskreen
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
Compartilhamento de Rede com samba em modo Público/Anônimo de forma simples, rápido e fácil
Cups: Mapear/listar todas as impressoras de outro Servidor CUPS de forma rápida e fácil
Criando uma VPC na AWS via CLI
Arch Linux - Guia para Iniciantes (2)
Problemas ao instalar o PHP (11)
Tem como instalar o gerenciador AMD Adrenalin no Ubuntu 24.04? (15)
Tenho dois Link's ( IP VÁLIDOS ), estou tentando fazer o failover... (0)