Renaming file with os.rename causing NameError - python

I'm trying to rename 2 raster files: old_name.jpg and old_name.tiff to new_name.jpg and new_name.tiff:
new_name = 'new_name' # defining new name here
for root_dir, dirname, filenames in os.walk(TargetDir):
for file in filenames:
if re.match(r'.*.jpg$', file, re.IGNORECASE) is not None: # converting jpg
os.rename(os.path.join(root_dir, file), os.path.join(root_dir, new_name + ".jpg"))
if re.match(r'.*.tiff$', file, re.IGNORECASE) is not None: # converting tiff
os.rename(os.path.join(root_dir, file), os.path.join(root_dir, new_name + ".tiff"))
It works on jpg like charm, but then throws
Traceback (most recent call last):
File "C:/!Scripts/py2/meta_to_BKA.py", line 66, in <module>
os.rename(os.path.join(root_dir, file), os.path.join(root_dir, new_name + ".tiff"))
NameError: name 'new_name' is not defined
Note that it uses new_name to rename jpg, but then variable vanishes in the very next block. I tried using shutil.move(), but got the same error. What is the problem?

The stack trace suggests that your snippet isn't the whole story.
I can't reproduce:
from __future__ import division, print_function, unicode_literals
import os
TargetDir = '/tmp/test'
new_name = 'new_name'
def main():
for root_dir, _, filenames in os.walk(TargetDir):
for filename in filenames:
if '.' not in filename:
continue
endswith = filename.rsplit('.', 1)[-1].lower()
if endswith not in set(['jpg', 'tiff']):
continue
new_filename = '{}.{}'.format(new_name, endswith)
from_fn = os.path.join(root_dir, filename)
to_fn = os.path.join(root_dir, new_filename)
print ('Moving', from_fn, 'to', to_fn)
os.rename(from_fn, to_fn)
if __name__ == '__main__':
main()
but I took the liberty of rewriting a bit.
> python hest.py
Moving /tmp/test/narf.jpg to /tmp/test/new_name.jpg
Moving /tmp/test/bla.tiff to /tmp/test/new_name.tiff

Related

Python: how can I move a file into a folder without overwriting it with the one already present?

def upload_image():
if lista_interventi.focus():
folder_check=Path(r"C:\GEC\image_DB")
if not folder_check.is_dir():
os.makedirs(r"C:\GEC\image_DB")
image = filedialog.askopenfilename(initialdir="", title="Seleziona il file",filetypes=(("jpg files", ".jpg"),("all files","(.xls")))
shutil.move(image, r"C:\GEC\image_DB"+"\"+ entry_claim.get()+ ".jpg")
messagebox.showinfo("Operazione riuscita", "Immagine inserita")
else: ### missing code
Here is a simple function that can take the source folder, destination folder and file name and move it while also checking if name exist and appending a count if need be.
import shutil
import os
source_dir = './images'
target_dir = './images2'
file_names = os.listdir(source_dir)
def move_file(from_dir, to_dir, file_name, addition=None):
if addition is None:
addition = 1
path = f'{to_dir}/{file_name}'
else:
filename, file_extension = os.path.splitext(f'{to_dir}/{file_name}')
path = f'{filename} ({addition}){file_extension}'.strip()
addition += 1
if os.path.isfile(path):
move_file(from_dir, to_dir, file_name, addition)
else:
shutil.copy(f'{from_dir}/{file_name}', path)
for file_name in file_names:
move_file(source_dir, target_dir, file_name)
In my case the before and after look like this:
Before structure of folders:
After:
As you can see the file darkred.png existed and so did darkred (1).png so the function correctly renamed the file darkred (2).png and moved it.

Renaming all files in a folder with python using specific condition

I have a folder which has files with names:
"fileX.JPG" where X = 1....N
and I want to name the files as :
"000000000X.JPG" where X=1...N
The new name of the file should have the number from the old name of the file plus the zeros. so example file names I want is:
0000000000001.jpg
0000000000011.jpg
0000000000111.jpg
etc
The file name is 13 characters long. so should have zeros accordingly.
I have not started my code. Don't know where should I start.
You can use os.rename() from the os module
for path in pathlib.Path("a_directory").iterdir():
if path.is_file():
old_name = path.stem
#original filename
old_extension = path.suffix
#original file extension
Also try 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'])))
directory = path.parent
#current file location
new_name = "text" + old_name + old_extension
path.rename(pathlib.Path(directory, new_name))
You can use os.rename.
For example:
for file in os.listdir():
# Get the number, e.g.:
old_number = file.strip("file")[1].strip(".JPG")[0]
os.rename(file, f"{old_number}.JPG")
You might have to adapt based on how your files are actually namd
import os
# Function to rename multiple files
def main():
for count, filename in enumerate(os.listdir("path-to-files")):
d = str(count).zfill(12)
dst = d + ".jpg"
src ='path-to-file'+ filename
dst ='path-to-file'+ dst
# rename() function will
# rename all the files
os.rename(src, dst)
# Driver Code
if __name__ == '__main__':
# Calling main() function
main()

I have to run my code twice to get desired outcome, why?

I'm finding that I have to run my code twice for the desired output and I'm not sure why. It's also printing a long string of letters in the shell that aren't needed. I'd just like it to be a bit cleaner.
The code creates folders with subfolders, based on files names, then moves the files into specific subfolders.
Filename example is "A123456-20190101-A01.mp3"
import os
import shutil
path = "/Volumes/ADATA UFD/For script/Files"
file_names = [file for file in os.listdir(path) if
os.path.isfile(os.path.join(path, file))]
file_map = {'O':'1-Original','P':'2-PreservationMaster','M':'3-Mezzanine','T':'4-Presentation','A':'5-Access','R':'6-Reference'}
parent_folders = set(file_name.rsplit('-', 1)[0] for file_name in file_names)
sub_folders = ['1-Original','2-PreservationMaster','3-Mezzanine','4-Presentation','5-Access','6-Reference']
for folder in parent_folders:
folder_path = os.path.join(path, folder)
try:
os.mkdir(folder_path)
except:
print('folder already exist:', folder_path)
for folders in sub_folders:
try:
folders_path = os.path.join(folder_path, folders)
os.mkdir(folders_path)
except:
print('folder already exists:', folders_path)
for file_name in file_names:
parent_folder = file_name.rsplit('-', 1)[0]
ext = file_name[19]
print(ext)
dest = os.path.join(path, parent_folder, file_map[ext.upper()], file_name)
src = os.path.join(path, file_name)
try:
shutil.move(src, dest)
except Exception as e:
print(e)
I'm getting this error message:
Traceback (most recent call last):
File "/Volumes/ADATA UFD/For script/MoveFilesToPreservationBundleTest3.py", line 30, in <module>
dest = os.path.join(path, parent_folder, file_map[ext.upper()], file_name)
builtins.KeyError: '0'

How do I rename multiple files in Python, using part of the existing name?

I have a few hundred .mp4 files in a directory. When originally created their names were set as "ExampleEventName - Day 1", "ExampleEventName - Day 2" etc. thus they are not in chronological order.
I need a script to modify each of their names by taking the last 5 characters in the corresponding string and add it to the front of the name so that File Explorer will arrange them properly.
I tried using the os module .listdir() and .rename() functions, inside a for loop. Depending on my input I get either a FileNotFoundError or a TypeError:List object is not callable.
import os
os.chdir("E:\\New folder(3)\\New folder\\New folder")
for i in os.listdir("E:\\New folder(3)\\New folder\\New folder"):
os.rename(i, i[:5] +i)
Traceback (most recent call last):
File "C:/Python Projects/Alex_I/venv/Alex_OS.py", line 15, in <module>
os.rename(path + i, path + i[:6] +i)
FileNotFoundError: [WinError 2] The system cannot find the file specified:
import os, shutil
file_list = os.listdir("E:\\New folder(3)\\New folder\\New folder")
for file_name in file_list("E:\\New folder(3)\\New folder\\New folder"):
dst = "!#" + " " + str(file_name) #!# meant as an experiment
src = "E:\\New folder(3)\\New folder\\New folder" + file_name
dst = "E:\\New folder(3)\\New folder\\New folder" + file_name
os.rename(src, dst)
file_name +=1
Traceback (most recent call last):
File "C:/Python Projects/Alex_I/venv/Alex_OS.py", line 14, in <module>
for file_name in file_list("E:\\New folder(3)\\New folder\\New folder"):
TypeError: 'list' object is not callable
Some other approach:
Not based on based length ( 5 for subname )
import glob
import os
# For testing i created 99 files -> asume last 5 chars but this is wrong if you have more files
# for i in range(1, 99):
# with open("mymusic/ExampleEventName - Day {}.mp4".format(i), "w+") as f:
# f.flush()
# acording to this i will split the name at - "- Day X"
files = sorted(glob.glob("mymusic/*"))
for mp4 in files:
# split path from file and return head ( path ), tail ( filename )
head, tail = os.path.split(mp4)
basename, ext = os.path.splitext(tail)
print(head, tail, basename)
num = [int(s) for s in basename.split() if s.isdigit()][0] #get the number extracted
newfile = "{}\\{}{}{}".format(head, num, basename.rsplit("-")[0][:-1], ext) # remove - day x and build filename
print(newfile)
os.rename(mp4, newfile)
You're having multiple problems:
You're trying to increment a value that should not be incremented. Also you've created the list file_list, and thus it should not take any arguments anymore.
When using the syntax:
for x in y:
you do not have to increment the value. It will simply iterate through the list until there is no more left.
Therefore you simply have to leave out the incrementation and iterate through the list file_list.
import os, shutil
file_list = os.listdir("E:\\New folder(3)\\New folder\\New folder")
for file_name in file_list: #removed the argument, the as file_list is a list and thus not callable.
dst = "!#" + " " + str(file_name) #!# meant as an experiment
src = "E:\\New folder(3)\\New folder\\New folder" + file_name
dst = "E:\\New folder(3)\\New folder\\New folder" + file_name
os.rename(src, dst)
#file_name +=1 removed this line
Now your solution should work.

Python recursive directory reading without os.walk

I am trying to walk through tree of directories and search for data in output text files by defining a recursive function (and not using os.walk) in Python.
import os
def walkfn(dirname):
if os.path.exists('output'):
file1 = open('output')
for line in file1:
if line.startswith('Final value:'):
print line
else:
for name in os.listdir(dirname):
path = os.path.join(dirname, name)
if os.path.isdir(path):
print "'", name, "'"
newdir = os.chdir(path)
walkfn(newdir)
cwd = os.getcwd()
walkfn(cwd)
I am getting the following error:
Traceback (most recent call last):
File "/home/Python Work/Test2.py", line 24, in <module>
walkfn(cwd)
File "/home/Python Work/Test2.py", line 19, in walkfn
walkfn(newdir)
File "/home/Python Work/Test2.py", line 12, in walkfn
for name in os.listdir(dirname):
TypeError: coercing to Unicode: need string or buffer, NoneType found
os.chdir() returns None, not the new directory name. You pass that result to the recursive walkfn() function, and then to os.listdir().
There is no need to assign, just pass path to walkfn():
for name in os.listdir(dirname):
path = os.path.join(dirname, name)
if os.path.isdir(path):
print "'", name, "'"
os.chdir(path)
walkfn(path)
You usually want to avoid changing directories; there is no need to if your code uses absolute paths:
def walkfn(dirname):
output = os.path.join(dirname, 'output')
if os.path.exists(output):
with open(output) as file1:
for line in file1:
if line.startswith('Final value:'):
print line
else:
for name in os.listdir(dirname):
path = os.path.join(dirname, name)
if os.path.isdir(path):
print "'", name, "'"
walkfn(path)

Categories