50

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.

Simplicity
  • 47,404
  • 98
  • 256
  • 385

8 Answers8

123

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.

noteness
  • 2,440
  • 1
  • 15
  • 15
  • 2
    Note, that this will also move the file to current directory. To avoid that, do `os.rename(os.path.join(path, file), os.path.join(path, str(i)+'.jpg'))` instead. – tavo May 26 '16 at 17:46
  • Also be careful about `join` method. Your code returns `TypeError: join() takes exactly one argument (2 given)`! To avoid that, simply replace the final row of your code by the following one: `os.rename(os.path.join(path, file), os.path.join(path, ''.join([str(index), '.jpg'])))`. – Jaroslav Bezděk Oct 14 '19 at 06:23
  • Thanks @JaroslavBezděk – noteness Oct 14 '19 at 19:00
  • And do think of `enumerate` as in this answer because otherwise you get a `ValueError: too many values to unpack (expected 2)` – Timo Sep 06 '22 at 08:09
  • Adding to @JaroslavBezděk `''.join()` takes an array as argument to join/concatenate text. – Timo Sep 06 '22 at 08:15
  • I write the simple way `os.rename(os.path.join(path, file), os.path.join(path, str(index)+ '.jpg'))` as seen [here further down](https://stackoverflow.com/a/61225172/1705829) – Timo Sep 06 '22 at 08:32
9

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)
Abid1174
  • 123
  • 1
  • 8
7
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()
Binayak
  • 71
  • 1
  • 2
2

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'))
martin jakubik
  • 4,168
  • 5
  • 29
  • 42
jayesh
  • 3,277
  • 1
  • 18
  • 7
1

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

sivi
  • 10,654
  • 2
  • 52
  • 51
0

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")
Dmitry
  • 6,716
  • 14
  • 37
  • 39
0

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 enter image description here

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 enter image description here

aljgom
  • 7,879
  • 3
  • 33
  • 28
  • thanks works great ! an better usage explanation would help, could move and rename directories with 3 line function and your rename_files.py confirm_and_rename function. – Pieter Nov 28 '21 at 09:04
0

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.