Renaming multiple files in a directory using Python - python

I'm trying to rename multiple files in a directory using this Python script:
import os
path = '/Users/myName/Desktop/directory'
files = os.listdir(path)
i = 1
for file in files:
os.rename(file, str(i)+'.jpg')
i = i+1
When I run this script, I get the following error:
Traceback (most recent call last):
File "rename.py", line 7, in <module>
os.rename(file, str(i)+'.jpg')
OSError: [Errno 2] No such file or directory
Why is that? How can I solve this issue?
Thanks.

You are not giving the whole path while renaming, do it like this:
import os
path = '/Users/myName/Desktop/directory'
files = os.listdir(path)
for index, file in enumerate(files):
os.rename(os.path.join(path, file), os.path.join(path, ''.join([str(index), '.jpg'])))
Edit: Thanks to tavo, The first solution would move the file to the current directory, fixed that.

You have to make this path as a current working directory first.
simple enough.
rest of the code has no errors.
to make it current working directory:
os.chdir(path)

import os
from os import path
import shutil
Source_Path = 'E:\Binayak\deep_learning\Datasets\Class_2'
Destination = 'E:\Binayak\deep_learning\Datasets\Class_2_Dest'
#dst_folder = os.mkdir(Destination)
def main():
for count, filename in enumerate(os.listdir(Source_Path)):
dst = "Class_2_" + str(count) + ".jpg"
# rename all the files
os.rename(os.path.join(Source_Path, filename), os.path.join(Destination, dst))
# Driver Code
if __name__ == '__main__':
main()

As per #daniel's comment, os.listdir() returns just the filenames and not the full path of the file. Use os.path.join(path, file) to get the full path and rename that.
import os
path = 'C:\\Users\\Admin\\Desktop\\Jayesh'
files = os.listdir(path)
for file in files:
os.rename(os.path.join(path, file), os.path.join(path, 'xyz_' + file + '.csv'))

Just playing with the accepted answer define the path variable and list:
path = "/Your/path/to/folder/"
files = os.listdir(path)
and then loop over that list:
for index, file in enumerate(files):
#print (file)
os.rename(path+file, path +'file_' + str(index)+ '.jpg')
or loop over same way with one line as python list comprehension :
[os.rename(path+file, path +'jog_' + str(index)+ '.jpg') for index, file in enumerate(files)]
I think the first is more readable, in the second the first part of the loop is just the second part of the list comprehension

If your files are renaming in random manner then you have to sort the files in the directory first. The given code first sort then rename the files.
import os
import re
path = 'target_folder_directory'
files = os.listdir(path)
files.sort(key=lambda var:[int(x) if x.isdigit() else x for x in re.findall(r'[^0-9]|[0-9]+', var)])
for i, file in enumerate(files):
os.rename(path + file, path + "{}".format(i)+".jpg")

I wrote a quick and flexible script for renaming files, if you want a working solution without reinventing the wheel.
It renames files in the current directory by passing replacement functions.
Each function specifies a change you want done to all the matching file names. The code will determine the changes that will be done, and displays the differences it would generate using colors, and asks for confirmation to perform the changes.
You can find the source code here, and place it in the folder of which you want to rename files https://gist.github.com/aljgom/81e8e4ca9584b481523271b8725448b8
It works in pycharm, I haven't tested it in other consoles
The interaction will look something like this, after defining a few replacement functions
when it's running the first one, it would show all the differences from the files matching in the directory, and you can confirm to make the replacements or no, like this

This works for me and by increasing the index by 1 we can number the dataset.
import os
path = '/Users/myName/Desktop/directory'
files = os.listdir(path)
index=1
for index, file in enumerate(files):
os.rename(os.path.join(path, file),os.path.join(path,''.join([str(index),'.jpg'])))
index = index+1
But if your current image name start with a number this will not work.

Related

LFW nested folder iteration [duplicate]

I'd like to browse through the current folder and all its subfolders and get all the files with .htm|.html extensions. I have found out that it is possible to find out whether an object is a dir or file like this:
import os
dirList = os.listdir("./") # current directory
for dir in dirList:
if os.path.isdir(dir) == True:
# I don't know how to get into this dir and do the same thing here
else:
# I got file and i can regexp if it is .htm|html
and in the end, I would like to have all the files and their paths in an array. Is something like that possible?
You can use os.walk() to recursively iterate through a directory and all its subdirectories:
for root, dirs, files in os.walk(path):
for name in files:
if name.endswith((".html", ".htm")):
# whatever
To build a list of these names, you can use a list comprehension:
htmlfiles = [os.path.join(root, name)
for root, dirs, files in os.walk(path)
for name in files
if name.endswith((".html", ".htm"))]
I had a similar thing to work on, and this is how I did it.
import os
rootdir = os.getcwd()
for subdir, dirs, files in os.walk(rootdir):
for file in files:
#print os.path.join(subdir, file)
filepath = subdir + os.sep + file
if filepath.endswith(".html"):
print (filepath)
Hope this helps.
In python 3 you can use os.scandir():
def dir_scan(path):
for i in os.scandir(path):
if i.is_file():
print('File: ' + i.path)
elif i.is_dir():
print('Folder: ' + i.path)
dir_scan(i.path)
Use newDirName = os.path.abspath(dir) to create a full directory path name for the subdirectory and then list its contents as you have done with the parent (i.e. newDirList = os.listDir(newDirName))
You can create a separate method of your code snippet and call it recursively through the subdirectory structure. The first parameter is the directory pathname. This will change for each subdirectory.
This answer is based on the 3.1.1 version documentation of the Python Library. There is a good model example of this in action on page 228 of the Python 3.1.1 Library Reference (Chapter 10 - File and Directory Access).
Good Luck!
Slightly altered version of Sven Marnach's solution..
import os
folder_location = 'C:\SomeFolderName'
file_list = create_file_list(folder_location)
def create_file_list(path):
return_list = []
for filenames in os.walk(path):
for file_list in filenames:
for file_name in file_list:
if file_name.endswith((".txt")):
return_list.append(file_name)
return return_list
There are two ways works for me.
1. Work with the `os` package and use `'__file__'` to replace the main
directory when the project locates
import os
script_dir = os.path.dirname(__file__)
path = 'subdirectory/test.txt'
file = os.path.join(script_dir, path)
fileread = open(file,'r')
2. By using '\\' to read or write the file in subfolder
fileread = open('subdirectory\\test.txt','r')
from tkinter import *
import os
root = Tk()
file = filedialog.askdirectory()
changed_dir = os.listdir(file)
print(changed_dir)
root.mainloop()

Python Script Saving/Copying into specific directory

I'm attempting to write a script that will save a file in the given directory, but I'm getting a NotADirecotryError[WinError 267] whenever I run it. Any ideas or tips on what I may have done incorrectly?
import shutil
import os
src = 'C:\\Users\\SpecificUsername\\Pictures\\test.txt\'
dest = 'C:\\Users\\SpecificUsername\\Desktop'
files = os.listdir(src)
for file in files:
shutil.copy(file, dest)
for file in files:
if os.path.isfile(file):
shutil.copy(file,dest) ```
There are a couple of things going on here:
You can just use forward slashes in the paths.
Your src is the test.txt file, and not a directory, so you cannot iterate over it using os.listdir().
You can also merge the two loops together since they are looping over the same set of data.
shutil.copy() takes a file path as input, while what you are passing is a filename.
The following code should work and it also copies directories as is:
import shutil
import os
basepath = "C:/Users/SpecificUsername/"
src = "Pictures/"
dest = "Desktop/"
files = os.listdir(os.path.join(basepath, src))
for filename in files:
filepath = os.path.join(basepath, src, filename)
if (os.path.isfile(filepath)):
print("File: " + filename)
shutil.copy(filepath,dest)
else:
print("Dir: " + filename)
shutil.copytree(filepath, os.path.join(dest, filename))
Hope it helps!

Renaming files with python in specific format

I'm trying to rename files in one folder, in the pattern 0001, 0002, 0010, 0100 etc. I'm very very new to python, so sorry for asking something so basic.
I've searched around, and most of the code I come across will rename files (not how I want it) or strip out certain characters. I've also come across code which uses extra modules (glob) which only take me further down the rabbit hole. Most of what I see just makes my head spin; at the moment my skills don't go beyond simple functions, if, when, for, while statements and so on.
I've cobbled together some code, that I (somewhat) understand, but it doesn't work.
import os
dir = os.listdir("D:\\temp\\Wallpapers")
i = 0
for item in dir:
dst ="000" + str(i) + ".jpg"
src = item
dst = item + dst
# rename() function will
# rename all the files
os.rename(src, dst)
i += 1
This is the error I get:
Traceback (most recent call last):
File "rename.py", line 14, in <module>
os.rename(src, dst)
FileNotFoundError: [WinError 2] The system cannot find the file specified: '00-Pyatna.jpg' -> '0000.jpg'
It doesn't work because you probably are not in the proper directory and you are trying to find those files in the directory you are located right now. You should do it using absolute paths. See the following code
import os
base_path = "D:/temp/Wallpapers"
files = os.listdir(base_path)
for i, fp in enumerate(files):
dst = os.path.join(base_path, "{0:04d}.jpg".format(i))
src = os.path.join(base_path, fp)
os.rename(src, dst)
Firstly, you can retrieve the maximum number already present in your folder with the following function
import re
def max_counter_in_files(folder):
files = os.listdir(folder)
maxnum = '0'
if files:
maxnum = max([max(re.findall("[\d]+", file)) for file in files])
return maxnum
For example, if your folder contains the files
file001.txt
file002.txt
file003.txt
then max_counter_in_files('path/to/your/files') would return 3.
Secondly, you can use that function to increment your next filename when adding new files. for example,
counter = int(self.max_counter_in_files(dest_path))
filename = f"filename{counter+1:04d}.txt"
filename would then be "filename0004.txt".

Trouble renaming files to customized names

Can't rename old files located in a folder in desktop. There are three files there item.pdf,item1.pdf and item2.pdf. What I wish to do now is rename those files to new_item.pdf,new_item1.pdf and new_item2.pdf.
I tried with the below script:
import os
filepath = "/Users/WCS/Desktop/all_files/"
for item in os.listdir(filepath):
os.rename(item,"new_name"+".pdf")
Executing the above script throws the following error. Whereas the folder address is accurate:
FileNotFoundError: [WinError 2] The system cannot find the file specified: 'item.pdf' -> 'new_name.pdf'
How can I rename these three files item.pdf,item1.pdf and item2.pdf to new_item.pdf,new_item1.pdf and new_item2.pdf from a folder?
Try this:
import os
import re
filepath = "/Users/WCS/Desktop/all_files/"
for item in os.listdir(filepath):
match = re.search(r'\d+$', item)
endnum = ""
if match:
endnum = match.group()
os.rename(os.path.join(filepath, item), os.path.join(filepath, "new_name{}.pdf".format(endnum)))
or, if you don't wanna use re
import os
filepath = "/Users/WCS/Desktop/all_files/"
for item in os.listdir(filepath):
new_name = item.replace('item', 'new_item')
os.rename(os.path.join(filepath, item), os.path.join(filepath, "new_name{}.pdf".format(new_name)))
You need to either specify the full path to your file in os.rename.
Something like:
for item in filepath:
os.rename(os.path.join(filepath, item), os.path.join(filepath, "new_item.pdf"))
Or change your current working directory to the directory where the files exist:
os.chdir("/your/file/path")
and then run your code.
See also https://docs.python.org/2/library/os.html#os.rename

Keeping renamed text files in original folder

This is my current (from a Jupyter notebook) code for renaming some text files.
The issue is when I run the code, the renamed files are placed in my current working Jupyter folder. I would like the files to stay in the original folder
import glob
import os
path = 'C:\data_research\text_test\*.txt'
files = glob.glob(r'C:\data_research\text_test\*.txt')
for file in files:
os.rename(file, file[-27:])
You should only change the name and keep the path the same. Your filename will not always be longer than 27 so putting this into you code is not ideal. What you want is something that just separates the name from the path, no matter the name, no matter the path. Something like:
import os
import glob
path = 'C:\data_research\text_test\*.txt'
files = glob.glob(r'C:\data_research\text_test\*.txt')
for file in files:
old_name = os.path.basename(file) # now this is just the name of your file
# now you can do something with the name... here i'll just add new_ to it.
new_name = 'new_' + old_name # or do something else with it
new_file = os.path.join(os.path.dirname(file), new_name) # now we put the path and the name together again
os.rename(file, new_file) # and now we rename.
If you are using windows you might want to use the ntpath package instead.
file[-27:] takes the last 27 characters of the filename so unless all of your filenames are 27 characters long, it will fail. If it does succeed, you've stripped off the target directory name so the file is moved to your current directory. os.path has utilities to manage file names and you should use them:
import glob
import os
path = 'C:\data_research\text_test*.txt'
files = glob.glob(r'C:\data_research\text_test*.txt')
for file in files:
dirname, basename = os.path.split(file)
# I don't know how you want to rename so I made something up
newname = basename + '.bak'
os.rename(file, os.path.join(dirname, newname))

Categories

Resources