Rename Files in C
Have you ever worked with a bunch of files and needed to rename them, using a given pattern? It could be very boring and frustrating.
That's where automation comes to help. Let's write a program in C to rename the files!
Be very careful if you make your own implementation of this program! Running the program with the wrong path will rename any files in that path and may damage the programs on your device.
What are the steps
To achieve our goal, we need to:
- Find the directory
- lists all files in that folder,
- Iterates through all of those files
- Rename them, using our pattern
Get the directory
We can approach this in 2 ways: rename the files in the current directory or use a parameter, which is given to us when the program is run.
Using the current directory
int main() {
char currentPath[256];
if (getcwd(currentPath, sizeof(currentPath)) == NULL) {
perror("Error getting current working directory");
return EXIT_FAILURE;
}
renameFilesInFolder(currentPath);
return EXIT_SUCCESS;
}
- int main(): This is the standard entry point for a C program that doesn't take any command-line arguments.
- char currentPath[256];: This line declares a character array named currentPath with a size of 256 characters. This array will be used to store the current working directory path.
- if (getcwd(currentPath, sizeof(currentPath)) == NULL): The getcwd function attempts to get the current working directory path and store it in the currentPath array. The sizeof(currentPath) specifies the size of the array to prevent buffer overflow. If getcwd fails, it returns NULL, indicating an error.
- perror("Error getting current working directory");: If the getcwd function fails (returns NULL), the perror function prints an error message to the console, describing the nature of the error. In this case, it indicates that there was an error while attempting to get the current working directory.
- return EXIT_FAILURE;: If there's an error while getting the current working directory, the program returns an error code EXIT_FAILURE to indicate that it did not run successfully.
- renameFilesInFolder(currentPath);: If the current working directory was successfully obtained, the renameFilesInFolder function is called with the currentPath as an argument. This function iterates through the files in the current directory and renames them.
- return EXIT_SUCCESS;: After the program completes successfully (i.e., after the files have been renamed), it returns the success code EXIT_SUCCESS.
This main function doesn't take any command-line arguments. Instead, it automatically determines the current working directory using the getcwd function and then proceeds to rename the files in that directory. If there's an error while obtaining the current directory, it displays an error message and returns a failure code.
Keep in mind that the executable file of the program will also be renamed, since it located in the current directory.
Passing the directory as a parameter
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <folder_path>\n", argv[0]);
return EXIT_FAILURE;
}
const char *folderPath = argv[1];
renameFilesInFolder(folderPath);
return EXIT_SUCCESS;
}
- int main(int argc, char *argv[]): This is the standard entry point for a C program. argc (argument count) indicates the number of command-line arguments passed to the program, and argv (argument vector) is an array of character pointers that point to the arguments.
- if (argc != 2): This condition checks if the number of command-line arguments is not equal to 2. The program expects the executable name and a single argument (the folder path). If this condition is true, it means the user didn't provide the correct number of arguments.
- printf("Usage: %s <folder_path>\n", argv[0]);: This line prints a usage message to the console. It uses argv[0] to print the name of the executable, informing the user about the correct usage of the program.
- return EXIT_FAILURE;: If the correct number of arguments is not provided, the program returns an error code EXIT_FAILURE to indicate that it did not run successfully.
- const char *folderPath = argv[1];: Assuming the correct number of arguments is provided, this line retrieves the folder path from the command-line argument. argv[1] points to the first argument after the executable name. This folder path is then stored in the folderPath variable.
- and 7. are the same as above
This main function reads a single command-line argument, which should be the path of the folder containing the files you want to rename. If the argument is missing or there are too many arguments, the program displays a usage message and returns an error. Otherwise, it proceeds to rename the files in the specified folder using the provided folder path.
Rename files in C
This example will rename all files in a given directory, so be very careful when running the code!
void renameFilesInFolder(const char *folderPath) {
DIR *dir = opendir(folderPath);
if (dir == NULL) {
perror("Error opening folder");
exit(EXIT_FAILURE);
}
struct dirent *entry;
int count = 0;
while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_REG) { // Regular file
count++;
char oldPath[256];
char newPath[256];
char *extension = strrchr(entry->d_name, '.'); // Get file extension
snprintf(oldPath, sizeof(oldPath), "%s/%s", folderPath, entry->d_name);
if (extension) {
snprintf(newPath, sizeof(newPath), "%s/f-%02d%s", folderPath, count, extension);
} else {
snprintf(newPath, sizeof(newPath), "%s/f-%02d", folderPath, count);
}
if (rename(oldPath, newPath) != 0) {
perror("Error renaming file");
exit(EXIT_FAILURE);
}
printf("Renamed: %s -> %s\n", oldPath, newPath);
}
}
closedir(dir);
}
- void renameFilesInFolder(const char *folderPath): This is a function that takes a single argument, folderPath, which is the path of the folder where the files should be renamed. It iterates through the files in this folder and renames them.
- DIR *dir = opendir(folderPath);: This line uses the opendir function to open the specified folder. It returns a pointer to a DIR structure, which represents the opened directory. If the folder cannot be opened (perhaps due to permission issues or if the folder doesn't exist), opendir returns NULL.
- if (dir == NULL) { ... }: This block of code checks if the folder was successfully opened. If dir is NULL, it means the folder couldn't be opened. An error message is printed using perror, and the program exits with a failure code.
- struct dirent *entry;: This declares a pointer to a struct dirent, which is used to represent directory entries (files and subdirectories) as they are being read from the directory using the readdir function.
- int count = 0;: This initializes a counter to keep track of the number of files processed. This counter will be used to create consecutive names like "f-01", "f-02", and so on.
- The while loop: This loop iterates through the directory entries using the readdir function. As long as there are more entries to read (entry is not NULL), the loop continues.
- if (entry->d_type == DT_REG) { ... }: Inside the loop, this condition checks if the current entry is a regular file. d_type is a field in the struct dirent that indicates the type of the entry. DT_REG stands for a regular file.
- char *extension = strrchr(entry->d_name, '.');: This line uses the strrchr function to find the last occurrence of the '.' character in the d_name field of the entry structure. If an extension exists, extension will point to the beginning of the extension including the dot.
We need this to preserve the original extensions of the files. - The if (extension) { ... } block: If an extension is found,
it appends the extension to the new file name format "f-01.ext". If
there's no extension, it uses the format "f-01" without an extension.
- Inside the inner block of the above condition:count++: Increment the file counter.char oldPath[256]; char newPath[256];: Declare character arrays to store the old and new paths of the file being processed.snprintf(oldPath, sizeof(oldPath), "%s/%s", folderPath, entry->d_name);: Create the old path by concatenating the folderPath and the name of the current file (entry->d_name).snprintf(newPath, sizeof(newPath), "%s/f-%02d", folderPath, count);: Create the new path with the desired format "f-01", "f-02", and so on, by appending the file counter to the folderPath.
- if (rename(oldPath, newPath) != 0) { ... }: This block attempts to rename the file using the rename function. If the renaming fails, it prints an error message using perror and exits the program with a failure code.
- printf("Renamed: %s -> %s\n", oldPath, newPath);: If the renaming is successful, this line prints a message indicating the old and new paths of the file.
- closedir(dir);: After all the files have been processed, this line closes the directory using the closedir function to release system resources.
In summary, the renameFilesInFolder function takes a folder path, iterates through the files in the folder, renames them using a counter, preserving the original file extensions and prints messages indicating the renaming process. If any error occurs during the process, appropriate error messages are displayed.
Entire example
The entire example is available on github. Be very careful when modifying or running the code, as renaming the files in the wrong directory can be pain in the you know what :)