A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://realpython.com/bulk-file-rename-tool-python/ below:

Build a Bulk File Rename Tool With Python and PyQt – Real Python

Say you need to rename multiple files in your personal folder using a specific naming pattern. Doing that manually can be time-consuming and error-prone. So, you’re thinking of automating the file renaming process by building your own bulk file rename tool using Python. If so, then this tutorial is for you.

In this tutorial, you’ll learn how to:

By completing the project in this tutorial, you’ll be able to apply a rich set of skills related to PyQt, Qt Designer, PyQt threads, and working with file system paths using Python’s pathlib.

You can download the final source code for the bulk file rename tool you’ll build in this tutorial by clicking the link below:

Get the Source Code: Click here to get the source code you’ll use to build a bulk file rename tool with Python in this tutorial.

In this tutorial, you’ll build a bulk file rename tool to automate the process of renaming multiple files in a given directory in your file system. To build this application, you’ll use Python’s pathlib to manage the file renaming process and PyQt to build the application’s graphical user interface (GUI).

Here’s how your bulk file rename tool will look and work once you get to the end of this tutorial:

Once you finish building the application, you’ll be able to rename multiple files in your file system, a common task when you’re organizing your personal files and folders. In this example, the application focuses on images and Python files, but you can add other file types as you go.

Project Overview

The project you’ll build in this tutorial consists of a GUI application that loads multiple files from a given directory and allows you to rename all those files in one go using a predefined filename prefix and consecutive numbers. In this section, you’ll take a first look at the problem and a possible solution. You’ll also figure out how to lay out the project.

Laying Out the Project

To build your bulk file rename tool, you’ll create a few modules and packages and organize them in a coherent Python application layout. Your project’s root directory will look like this:

./rprename_project/
│
├── rprename/
│   │
│   ├── ui/
│   │   ├── __init__.py
│   │   ├── window.py
│   │   └── window.ui
│   │
│   ├── __init__.py
│   ├── app.py
│   ├── rename.py
│   └── views.py
│
├── README.md
├── requirements.txt
└── rprenamer.py

Here, rprename_project/ is the project’s root directory, where you’ll create the following files:

Then you have the rprename/ directory that will hold a Python package with the following modules:

The ui/ subdirectory will provide a package to store GUI-related code. It’ll contain the following files and modules:

Go ahead and create this directory structure with all the files and modules except for window.ui and window.py. You’ll see how to create these two files with Qt Designer and pyuic5 later in this tutorial.

To download the project’s directory structure, click the link below:

Get the Source Code: Click here to get the source code you’ll use to build a bulk file rename tool with Python in this tutorial.

Outlining the Solution

Your bulk file rename tool will be a fully functional GUI application. It’ll allow you to load several files from an existing directory and rename them using a descriptive filename prefix and consecutive numbers. To build the application, you’ll need to take the following steps:

  1. Create the application’s GUI.
  2. Provide the functionality to load and rename multiple files.
  3. Update the application’s GUI according to the file renaming process progress.

To create the application’s GUI, you’ll use Qt Designer. This tool provides a user-friendly interface to create GUIs by dragging and dropping graphical components (widgets) on a blank form. With this tool, your GUI creation process will be fast and productive.

When it comes to managing files and directories in Python, you have several options in the standard library. For example, you have os.path to work with file system paths and os to use operating system functionalities, such as renaming files with os.rename(). In this tutorial, however, you’ll use pathlib for both tasks.

Note: Python 3.4 added pathlib to the standard library. This module provides classes that represent file system paths and allow operations on them.

Typically, you’ll use pathlib.Path to manage file and directory paths in your applications. Once you have a Path object that points to a physical file or directory, you can call .rename() on that object to rename the associated file or directory.

Next, you need to code the functionality to load multiple files into your application and rename them in one go. Depending on the number of files that you need to rename, the operation can take a considerable amount of time. This might cause your application’s GUI to freeze. To prevent GUI freezing issues, you’ll offload the renaming process to a worker thread using QThread.

The file renaming process needs to be connected with the application’s GUI so the user knows what is happening at any given time. In this example, you’ll set up a progress bar to reflect the operation progress.

You’ll also write some code to ensure that the GUI gets updated according to the file renaming progress and state. There are at least two general strategies for managing the GUI update:

  1. Using conditional statements to check the state and take actions accordingly
  2. Enabling and disabling widgets depending on the application’s state.

In this project, you’ll use the second approach, which might be more intuitive and user-friendly, providing a better user experience.

Prerequisites

To complete this tutorial and get the most out of it, you should be comfortable with the following concepts:

If you don’t have all the required knowledge, then that’s okay! You can start the tutorial and take some time and review the following resources whenever you need to:

Additionally, you can take a look at the following resources:

In terms of external software dependencies, your bulk file rename tool depends on PyQt v5.15.12. You can install this library from PyPI using pip as usual:

Finally, you should create a virtual environment to isolate your project’s dependencies as Python best practices recommend. After that, it’s time to start working on your own bulk file rename tool!

In this section, you’ll use Qt Designer to quickly create the bulk file rename tool’s GUI. At the end of this step, you’ll have a Qt Designer’s .ui file providing the required code for the following window:

You’ll also learn how to automatically translate your .ui file into Python code. You’ll use that code to provide the GUI for your application’s main window.

To download these files and all the code you’ll write in this section, click the link below:

Get the Source Code: Click here to get the source code you’ll use to build a bulk file rename tool with Python in this tutorial.

Creating the GUI With Qt Designer

To start working on your bulk file rename tool’s GUI, go ahead and fire up Qt Designer. Then create a widget-based form and run the steps shown in the following video:

Here are the steps in the above video:

  1. Create a new form using the Widget template from the New Form dialog and set its title to RP Renamer.
  2. Add a label and set its text to Last Source Directory:.
  3. Add a line edit to hold the path to the selected directory and set its .readOnly property to True.
  4. Add a push button and set its text to &Load Files.
  5. Add two labels with the text Files to Rename and Renamed Files, respectively, and set their font style to Bold.
  6. Add two list widgets to display the files to rename and the renamed files, respectively.
  7. Set a vertical layout to the labels and their corresponding list widgets.
  8. Join both arrangements using a splitter.
  9. Add a label and set its text to Filename Prefix:.
  10. Add a line edit to take the filename prefix from the user and set its placeholder text to Rename your files to….
  11. Add a label and set its text to .jpg.
  12. Add a push button and set its text to &Rename.
  13. Add a progress bar and set its value to 0.
  14. Tweak the minimumSize and maximumSize properties of labels, line edits, and push buttons to provide a coherent resizing behavior when the user resizes the window.
  15. Set a grid layout as the form’s top-level layout.

Once you’re done, save the form as window.ui under the rprename/ui/ directory. Don’t close Qt Designer. Go ahead and change the .objectName property for the following objects:

Object Value Form Window lineEdit dirEdit pushButton loadFilesButton listWdget srcFileList listWidget_2 dstFileList lineEdit_2 prefixEdit label_5 extensionLabel pushButton_2 renameFilesButton

To do that, you can select the object in the Object Inspector and change the property value in the Property Editor:

You need to change the object names because you’ll use those names in your Python code, so they should be more descriptive and readable. Now go ahead and click Save on Qt Designer’s toolbar to make the new object names persistent in your window.ui file. You can also save the file by pressing Ctrl+S on your keyboard.

Once you’ve finished building the bulk file rename tool’s GUI, you can close Qt Designer since you won’t need it any longer. Next, you need to translate the content of the .ui file you just created into Python code. That’s what you’ll do in the following section.

Converting Qt Designer’s Output Into Python Code

Once you have a .ui file with a suitable GUI for your application, you need to convert the content of this file into Python code so you can load the GUI in the final application. PyQt provides a command-line tool called pyuic5 that allows you to perform this conversion.

Note: You can also load the content of a .ui file into your application directly using uic.loadUi(). This strategy, however, is mostly recommend for small dialogs.

If you take a look at the content of your window.ui file, then you’ll see that it contains XML code. That code defines all the graphical components for your application’s GUI. Here’s a fragment of the file content:

In this small fragment, the definition of Window is the top-level class. This class represents your main window. Then the XML code defines other classes and sets their properties. Since PyQt provides pyuic5 to automatically translate this XML code into Python code, you don’t need to worry about the content of your .ui files. You just need to know how to use pyuic5.

Now open a terminal on your rprename/ui/ directory and run the following command:

This command generates a Python module called window.py from the window.ui file and places it in your rprename/ui/ directory. The module contains the Python code for your bulk file rename tool’s GUI. Here’s a small sample of the code:

Ui_Window provides all the code for generating the GUI of your bulk file rename tool. In this case, .setupUi() contains the code to create all the required widgets and also to lay them out on the GUI, while .retranslateUi() contains code for internationalization and localization, which is beyond the scope of this tutorial.

Since you’re using pyuic5 to automatically generate the Python code from an existing .ui file, you don’t need to worry about the content of window.py. Like the WARNING! comment at the top of the file states, all the changes you make to this file will disappear if you update the GUI with Qt Designer and regenerate the Python code.

Having a module with GUI-specific code strongly encourages the separation of GUI logic from business logic, which is a fundamental principle in the Model-View-Controller pattern.

At this point, your project’s layout is complete. You have all the files you need to create your bulk file rename tool. Now it’s time to put together the skeleton PyQt application using the GUI you just created.

Step 2: Create the PyQt Skeleton Application

So far, you’ve built a GUI for the bulk file rename tool using Qt Designer. You also used pyuic5 to automatically translate the .ui file content into Python code so you can use it in the application. Finally, you saved the code into window.py under the rprename/ui/ directory.

In this section, you’ll create a PyQt skeleton application and set its main window to use the GUI code you have in window.py. To download the files and all the code you’ll write in this section, click the link below:

Get the Source Code: Click here to get the source code you’ll use to build a bulk file rename tool with Python in this tutorial.

Setting Up the Bulk File Rename Tool’s Window

To create the skeleton PyQt application for your bulk file rename tool, you first need to create the application’s main window. First, fire up your favorite code editor or IDE and open the rprename/__init__.py file. Add the following content to it:

Other than some comments and the module docstring, the above file defines a top-level constant called __version__ to hold the application’s version number.

Next, open rprename/views.py and write the following content into it:

In views.py, you first import QWidget from PyQt5.QtWidgets. Then you import Ui_Window from ui.window. As you saw before, this class provides the GUI for your bulk file rename tool.

Next, you create a new class called Window. This class uses multiple inheritance. It inherits from QWidget and also from your GUI class, Ui_Window. QWidget enables the base GUI functionality, and Ui_Window provides the specific GUI arrangement you want for this application.

Note: You can also use composition to create the GUI for your Window.

For example, you can define Window like this:

In this case, you create .ui as an instance of Ui_Window. From this point on, you need to use .ui to access the widgets on the application’s GUI.

In this tutorial, you use the multiple inheritance approach because it makes all the user interface components directly accessible without the need for the .ui attribute. For a deeper dive into this topic, check out Using a Designer UI File in Your Application.

The initializer of Window calls the base class initializer using super(). It also calls ._setupUI(), which is a non-public method that will collect all the code required for generating and setting up the GUI. Up to this point, ._setupUI(self) only calls .setupUi(), which is provided by the second parent class, Ui_Window.

Note: Python doesn’t distinguish between private and public attributes. The term non-public in the above paragraph refers to those attributes that aren’t intended to be used from outside the containing class. The Python naming convention for this kind of attribute is to use a leading underscore (_) in the name.

With the initial version of Window ready for use, you can go ahead and create a PyQt skeleton application for your bulk file rename tool.

Creating the PyQt Skeleton Application

Now that you have the application’s main window ready for use, it’s time to write the required boilerplate code to create a PyQt application. Get back to your code editor and open the rprename/app.py file. Then add the following code:

In this module, you import sys to access exit(). This function allows you to cleanly exit the application when the user closes the main window. Then you import QApplication from PyQt5.QtWidgets and Window from views. The final step is to define main() as your application’s main function.

In main(), you instantiate QApplication and Window. Then you call .show() on Window. Finally, you run the application’s main loop or event loop using .exec().

Coding the Application’s Entry-Point Script

With the PyQt skeleton application in place, you can create a suitable entry-point script so you can run the application quickly. Open the rprenamer.py file from your root directory and type the following code into it:

This script is fairly small. You first import main() from your app.py module. Then you use the traditional Python conditional statement that calls main() if the user runs the module as a Python script.

Now you can open a terminal and run the script to launch the application. You’ll get the following window on your screen:

Cool! Your bulk file rename tool has a nice GUI that provides a button to load the files you want to rename. The top line edit will show the path to the source directory. The left-side list widget will display the list of files to be renamed, and the right-side list widget will show the renamed files.

To kick off the file renaming process, the user needs to provide a filename prefix and then click Rename. The progress bar at the bottom will show the file renaming progress.

In the next section, you’ll write the required code to provide the application’s main functionality, renaming multiple files in one go. So close the application’s window to continue adding features.

Step 3: Rename Files With pathlib and PyQt Threads

To implement the file renaming functionality for your bulk file rename tool, you’ll use Python’s pathlib and PyQt QThread. With pathlib, you’ll manage file system paths and rename files. With QThread, on the other hand, you’ll rename files in a separate thread of execution. Why?

Well, depending on the number of files that you want to rename, the renaming process might take a considerable time. Launching a long-running task in the application’s main thread can freeze the GUI, which in turn can result in a bad user experience.

To avoid GUI freezing issues, you can create a worker QThread to offload the file renaming process and make your application responsive.

Again, you can download all the code you’ll write in this section by clicking the link below:

Get the Source Code: Click here to get the source code you’ll use to build a bulk file rename tool with Python in this tutorial.

Loading and Displaying Target Files

To start renaming files, you first need a way to load those files into the application. PyQt provides a class called QFileDialog that allows you to select files or directories from your file system using a predefined dialog. Once you select the files you want to rename, you need to store their paths in a convenient data structure.

Get back to the rprename/views.py and update the code like this:

Here, you first import deque from collections. Deques are a generalization of stacks and queues. They support efficient append and pop operations from either side of the deque. In this case, you’ll use a deque to store the paths of the files you need to rename.

You also import Path from pathlib. This class can represent concrete file or directory paths in your file system. You’ll use this class to perform different operations on files and directories. In this tutorial, you’ll use Path.rename() to rename physical files in your hard drive.

Then you import QFileDialog from PyQt5.QtWidgets. This class provides an appropriate dialog to select files from a given directory. The FILTER constant specifies different file filters as a string. These filters allow you to select from different file types when loading files into the application.

Keep views.py open and update Window like this:

Here’s what the newly added code does:

Then you define .loadFiles() to load the files that you want to rename. Here’s what it does:

If you run the application now, then you’ll get the following behavior:

Now you can load multiple files into your bulk file rename tool by clicking Load Files. Note that you can specify the file type you want to load into the application by choosing from several file filters in the Choose Files to Rename dialog.

Note: The line numbers in the above code and in the rest of the code samples in this tutorial are intended to facilitate the explanation. They don’t match the order of lines in the final module or script.

Cool! Your project already has support for loading files of different types. Go ahead and close the application to continue coding. In the next section, you’ll implement the file renaming functionality.

Renaming Multiple Files in a Worker QThread

To perform the file renaming process, you’ll use a QThread object. Creating and setting up a worker thread allows you to offload the file renaming process from the application’s main thread. This way you prevent possible freezing GUI issues when you select a big number of files to rename.

The worker thread will perform the file renaming using pathlib.rename(). It’ll also emit custom signals to communicate with the main thread and update the application’s GUI. Go ahead and open the rprename/rename.py file in your code editor. Type in the following code:

Here’s what this code does:

The class initializer on line 17 takes two required arguments:

  1. files holds the list of selected files. Each file is represented by its corresponding Path.

  2. prefix holds the filename prefix that you’ll use to rename the files.

Then you define the method that performs the file renaming process, .renameFiles(). Here’s a summary of how it works:

Once you’ve coded Renamer, you’re ready to start renaming files. To do that, you need to create and set up a worker thread. But first, get back to rprename/views.py and update its import section like this:

In the first highlighted line, you import QThread from PyQt5.QtCore. This class allows you to create and manage worker threads in PyQt applications. In the second highlighted line, you import Renamer from your rename module.

Now scroll down a little bit in your views.py file and update Window like this:

Here, you first connect the Rename button’s .clicked() to .renameFiles(). This method calls ._runRenamerThread() to create, set up, and run the worker thread. Here’s how it works:

The final piece of code defines ._updateStateWhenFileRenamed(). When a file is renamed, the method removes the file from the list of files to be renamed. Then the method updates the list of Files to Rename and also the list of Renamed Files on the application’s GUI.

Here’s how the application works now:

That’s it! Your bulk file rename tool already does its job. It allows you to load several files, provide a new filename prefix, and rename all the selected files. Great job!

Now you can close the application to continue with the development process. In the next section, you’ll learn how to update the application’s GUI according to the file renaming progress.

Step 4: Update the GUI State According to the Renaming Progress

So far, your bulk file rename tool provides its main functionality. You can already use the tool to rename multiple files in your file system. However, what would happen if the user clicked Rename in the middle of the renaming process? Also, what if the user forgets to supply an appropriate filename prefix?

Another and even more visible issue is why the application’s progress bar doesn’t reflect the file renaming progress.

All these questions have to do with updating the GUI according to the application’s state at any given time. In this section, you’ll write the required code to fix or prevent the issues mentioned above. You’ll start with the progress bar.

You can download the code you’ll write in this section by clicking the link below:

Get the Source Code: Click here to get the source code you’ll use to build a bulk file rename tool with Python in this tutorial.

Updating the Progress Bar

In GUI applications, you typically use progress bars to inform your users about the progress of long-running tasks. If the users don’t get feedback on what the application is currently doing, then they might think that the application is frozen, stuck, or is having some internal issues.

In this project, you use a progress bar to provide feedback on how the file renaming process is going at any given time. To do that, get back to the rprename/views.py in your code editor and update it like this:

Here’s what the newly added code does:

That’s it! Go ahead and run your application again. It’ll work like this:

After these additions to Window, the progress bar of your bulk file rename tool reflects the progress of the file renaming operation, which is nice and improves your users’ experience.

Enabling and Disabling GUI Components

When you build GUI applications, you realize that some actions on the GUI are only available in certain situations. In your bulk file rename tool, for example, it doesn’t make sense to allow the user to click Rename if there’s no file already loaded into the application or if the user hasn’t provided a filename prefix.

There are at least two ways to deal with this kind of situation:

  1. Leave all the widgets enabled all the time and make sure that they don’t trigger any actions that don’t make sense in context.
  2. Enable and disable widgets depending on the application’s state.

To implement the first approach, you can use conditional statements to make sure a given action makes sense at a given moment. To implement the second approach, on the other hand, you need to figure out all the possible states your application can run into and provide methods to update the GUI accordingly.

Note: When you disable a PyQt widget or graphical component, the library grays out the widget at hand and makes it unresponsive to the user’s events, such as a click and a keypress.

In this tutorial, you’ll use the second approach, which might be more intuitive and user-friendly. To do that, you need to figure out the possible states the application can run into. Here’s a first approach to this problem:

State Description Method No files loaded The application is running, and the list of Files to Rename is empty. ._updateStateWhenNoFiles() Files loaded The list of Files to Rename contains one or more files. ._updateStateWhenFilesLoaded() Ready to rename files The list of Files to Rename contains one or several files, and the user has provided a filename prefix. ._updateStateWhenReady() Renaming files The user has clicked Rename, and the file renaming process has started. ._updateStateWhileRenaming() Renaming done The file renaming process has finished, and there are no left files to rename. ._updateStateWhenNoFiles()

Since the first and the last states in the above table are quite similar, you’ll use the same method to update the GUI. That means you only have to implement four methods.

To start coding these methods, get back to views.py and add the following code to Window:

Here’s how this update works:

When you run the application, you can press Space on your keyboard to launch the dialog and select the files you want to rename. Also, the Filename Prefix line edit and the Rename button are disabled so you can’t perform actions on them.

Now you can code the method to update the GUI when you load files into the application. Add the following code to Window:

When you load one or more files into the application, .loadFiles() calls ._updateStateWhenFilesLoaded(). This method enables the Filename Prefix line edit so you can enter a prefix to use for renaming files. It also moves the focus to that widget so you can provide a filename prefix immediately.

Next, you can code the method to handle the GUI update when the application is ready to rename a bunch of files. Add the following code to Window:

Here, you first connect the Filename Prefix line edit’s .textChanged() signal with ._updateStateWhenReady(). This method enables or disables the Rename button according to the content of the Filename Prefix line edit. This way, when the line edit is empty, the button gets disabled, and otherwise it’s enabled.

Finally, you need to code the method to handle the GUI update when the application is renaming your files. Go ahead and add the following code to Window:

When your user clicks Rename, the application starts the file renaming process and calls ._updateStateWhileRenaming() to update the GUI accordingly. The method disables the Load Files and Rename buttons so the user can’t click them while the renaming process is running.

That’s it! If you run the application now, then you’ll get the following behavior:

Your bulk file rename tool’s GUI now reflects the application’s state at any given time. This allows you to offer your users an intuitive, frustration-free experience. Great job!

Conclusion

Automatically renaming multiple files is a common problem when you’re organizing your personal files and folders. In this tutorial, you built a real-world GUI application to perform this task quickly and efficiently. By building this tool, you applied a wide range of skills related to creating GUI applications with PyQt and Qt Designer. You also worked with files using Python’s pathlib.

In this tutorial, you learned how to:

You can download the final source code for the bulk file rename project by clicking the link below:

Get the Source Code: Click here to get the source code you’ll use to build a bulk file rename tool with Python in this tutorial.

Next Steps

Up to this point, you’ve built a real-world application to automate the process of renaming multiples files. Even though the application provides a minimal set of features, it’s a good starting point for you to continue adding features and learning along the way. This will help you take your skills with Python and PyQt GUI applications to the next level.

Here are some ideas you can implement to continue improving the project:

These are just a few ideas of how to continue adding features to your bulk file rename tool. Take the challenge and build something amazing!


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4