renaming multiple files in a repository
I have created on web service “GitHub” (hereinafter I will call it “GitHub” so that I can incline) a repository into which I gradually uploaded files through the web interface, both one by one and in groups. At the moment, this repository stores about one and a half hundred files in different folders, including nesting folders of different depths. The files have different extensions.
I needed to rename 157 files at once in the described repository according to the following principle:
00-00_имя-файла.ext # было
00-000_имя-файла.ext # стало, добавился '0'
This block of code shows templates. Instead of .ext
there may be different extensions (in my case, these are extensions .cpp
And .h
). Instead of имя-файла
there may be different names of several words, these names can be of different lengths. Instead of 00-00
there may be, for example, the following character sequences: 00-01
, 00-02
…, 01-00
, 01-01
…, 02-00
, 02-01
, 02-02
and so on. That is, I needed to expand the second number that comes after the hyphen from two digits to three, so I need to rename all files by adding the symbol 0
to the above location in the file name.
I know how you can rename files one by one through the Github web interface, you can read about this in separate article the Github documentation, but it does not describe how to rename many project files at once. I didn’t manage to do it quickly, in one operation, so I broke the task into several simpler points.
Action plan
Clone the repository (create a copy) on your computer;
Write a script to rename multiple project files and rename them;
Create a commit with all renames;
Push changes to the original GitHub repository.
1. Clone the repository on your computer
I work on the Windows 10 operating system and use the program (version control system) “Git for Windows‘ from the command line. As a shell program I use “PowerShell” version 7. As a “terminal emulator” program I use “Windows Terminal“.
Cloning (creating a copy) of the repository from Github to my computer (sometimes I will shorten the path to the current location with an ellipsis ...
so that the command fits into the article format):
PS C:\...\repos> git clone https://github.com/ilyachalov/learncpp-com-examples
team git clone
we just pass the URL of the repository on Github. Authorization is not required. As far as I understand, this is because this is my repository public. As a result of this command, a folder “learncpp-com-examples” with repository files was created in the current location. For further actions, it is more convenient to go to this folder and work from it.
PS C:\Users\Илья\source\repos> cd learncpp-com-examples
PS C:\Users\Илья\source\repos\learncpp-com-examples>
For convenience, I will refer to this location as follows:
PS ..\learncpp-com-examples>
2. Script for renaming files and its application
For the basis of the script, I took the code from example 4 articles about the cmdletRename-Item» documentation of the “PowerShell” wrapper program. I rewrote that code for my needs, added regular expressions and got the following:
file “rename-files.ps1” (in UTF-8 encoding without BOM, CRLF line endings)
Get-ChildItem -File -Recurse |
Rename-Item -NewName {
$_.Name -replace '^(\d\d)-(\d\d)_(.*)', '$1-0$2_$3'
}
This script only looks at files (folders are discarded, this is ensured by the parameter -File
cmdlet “Get-ChildItem”), starting from the current folder and moving deeper into subfolders (this is provided by the parameter -Recurse
cmdlet “Get-ChildItem”). The “Get-ChildItem” cmdlet selects all files, so the parameter -Path
the “Get-ChildItem” cmdlet is not required, it is omitted. Files selected by the Get-ChildItem cmdlet are piped |
cmdlet “Rename-Item”, which performs the renaming.
I wrote another version of this script that does the same thing, but also prints messages to the console window during its execution, informing about the progress of the renames. At the end of the work, it issues a message to the console window with information about the number of files viewed, as well as how many of the viewed files were renamed:
file “rename-files.ps1” (in UTF-8 encoding without BOM, CRLF line endings)
$total = 0
$renamed = 0
Get-ChildItem -File -Recurse |
Rename-Item -NewName {
$old = $_.Name
$new = $old -replace '^(\d\d)-(\d\d)_(.*)', '$1-0$2_$3'
$script:total++
if ($old -ne $new) {
Write-Host "$old --> $new"
$script:renamed++
} else {
Write-Host "$new"
}
$new
}
"Проверено файлов всего: $total, из них переименовано: $renamed"
I have more detailed analysis this script.
To rename the files, I placed the file “rename-files.ps1” with the script in the desired folder of the cloned repository and ran it:
PS C:\Users\Илья\source\repos\learncpp-com-examples\chapters> .\rename-files
rename-files.ps1
00-00_helloworld.cpp --> 00-000_helloworld.cpp
00-01_helloworld-wait.cpp --> 00-001_helloworld-wait.cpp
00-02_cpp17compat.cpp --> 00-002_cpp17compat.cpp
00-03_cpp20compat.cpp --> 00-003_cpp20compat.cpp
01-00_snippet.cpp --> 01-000_snippet.cpp
...
02-98_io.cpp --> 02-098_io.cpp
02-98_main.cpp --> 02-098_main.cpp
02-99_io.cpp --> 02-099_io.cpp
02-99_io.h --> 02-099_io.h
02-99_main.cpp --> 02-099_main.cpp
Проверено файлов всего: 158, из них переименовано: 157
After the renaming is completed, the file “rename-files.ps1” of the script should be deleted from the project folder so that it does not interfere with the creation of the commit.
3.1. Checking Git repository settings
Before creating a commit that will later go to Github, it makes sense to check the setting of the name of the author of the commit and the email address of the author of the commit, if you do not want to “shine” them on the Internet.
To check the settings of the Git repository, it is convenient to use the following command from the project folder (thanks to the parameter --show-origin
you will be able to see in which files the Git repository settings are stored; often different settings are stored in different files):
PS ..\learncpp-com-examples> git config --list --show-origin
To view only the two settings I’m interested in (name of the commit author, his email address), you can use the following two commands:
PS ..\learncpp-com-examples> git config user.name
Ilya Chalov
PS ..\learncpp-com-examples> git config user.email
почта@домен.ru
I have such a name and it is registered on Github, but I would not want to “shine” the email address there. Github, at the request of the user, creates a “service” email address for commits performed through the web interface, which “covers” the user’s real email address.
This “service” email address can be viewed in the settings of your GitHub account (“Settings / Emails” menu, if you enter through your avatar in the upper right corner of the web service pages) at the following URL (it will work if you are already authorized on the web service):
Меню «Settings / Emails» (если заходить через свою аватарку)
https://github.com/settings/emails
I change the email address in the settings of the current one (parameter --local
) Git repository:
PS ..\learncpp-com-examples> git config --local user.email служебный@github.com
3.2. Creating a commit with all renames
team git mv
I couldn’t use it for renaming, because it seems that you can’t use regular expressions in it (you can use wildcards, but they are not enough). However, as write in a famous book about “Git”, actually the command git mv
is a combination of three commands: 1) renaming a file using the operating system or using other programs, 2) git rm
for file with name before renaming, 3) git add
for the file with the name after renaming.
Point one of the three above, I have already completed earlier using my script “rename-files.ps1”. The remaining two steps can be done for all 157 renamed files with one command:
PS ..\learncpp-com-examples> git add --all
Now all the changes are placed in the index and you can finally create a commit:
PS ..\learncpp-com-examples> git commit -m "Переименование группы файлов (157 штук)"
4. Sending changes to the original repository on Github
Authorization is required when submitting changes to the original Github repository. When I tried to enter my password, Github told me that as of August 13, 2021, password authentication is no longer used. I was prompted to go into the documentation for following link and read about the valid methods of authentication.
I chose the authentication method using an access token and created granulated access token (now on Github there are two valid implementations of access tokens: the old (classic) and the new (granular access tokens, in English “fine-grained access token”)). I have a separate detailed article about creating a granular access token. Using an access token is easy: when authenticating, you just need to enter it (paste from the clipboard) instead of a password.
I send the changes to the original repository on GitHub:
PS C:\Users\Илья\source\repos\learncpp-com-examples> git push origin main
Username for 'https://github.com': ilyachalov
Password for 'https://ilyachalov@github.com':
When entering a password (in my case, an access token), the input is not reflected in the console window, but in reality it occurs. This approach is probably taken for security reasons so that no outsider can see the length of the input character sequence.
Conclusion
After pushing the changes to Github, I opened the original repository in a browser and checked to see if the commit was received. Everything worked out just as I planned. Here is the link to the commit renaming 157 files at once in the original repository.