OS.RENAME - Problem with double/quadruple slashes - python

I'm attempting to rename a file and am successful in doing so until the last line below. Using os.rename, no matter what I've tried (f strings for example) I just can't get it to work. I'm getting quadruple and double slashes in the output. I'm sure it's a simple resolution. Any help would be greatly appreciated.
import os
from os import path
import shutil
from datetime import date
WDPath = r'\\xxx\yyy\gis\SAP_IMPORT_SQLARCGIS'
ARCHIVE_PATH = r'\\xxx\yyy\gis\SAP_IMPORT_SQLARCGIS\ARCHIVE\GISDEVICES'
IMPORT_FILE_NAME = r'\GISDEVICES.txt'
IMPORT_FILE = os.path.join(f'{WDPath}{IMPORT_FILE_NAME}')
print(IMPORT_FILE, '\n')
# split the file into filename and extension
filename, extension = os.path.splitext(IMPORT_FILE_NAME)
print(filename, extension, '\n')
# Get the create time of the file
create_time = os.path.getctime(IMPORT_FILE)
print(create_time, '\n')
# get the readable timestamp format
## format_time = datetime.datetime.fromtimestamp(create_time)
format_time = date.fromtimestamp(create_time)
print(format_time, '\n')
# convert time into string
format_time_string = format_time.strftime("-%Y-%m-%d")
print(format_time_string, '\n')
# Contruct the new name of the file
newfile = filename + format_time_string + extension
print(newfile, '\n')
# rename the file
os.rename(IMPORT_FILE, newfile)
print(IMPORT_FILE)
RESULT >>
\\nasgriver\SAP_Share\gis\SAP_IMPORT_SQLARCGIS\GISDEVICES.txt
\GISDEVICES .txt
1614332702.039849
2021-02-26
-2021-02-26
\GISDEVICES-2021-02-26.txt
Traceback (most recent call last):
File "\\xxx\yyy\gis\SAP_IMPORT_SQLARCGIS\MOVERENAMEFILE.py", line 42, in <module>
os.rename(IMPORT_FILE, newfile)
OSError: [WinError 17] The system cannot move the file to a different disk drive: '\\\\xxx\\yyy\\gis\\SAP_IMPORT_SQLARCGIS\\GISDEVICES.txt' -> '\\GISDEVICES-2021-02-26.txt'

Using the path submodule of os can come with some annoyance, you can try with pathlib instead:
import os
from pathlib import Path
import shutil
from datetime import date
WDPath = Path(r"\\xxx\yyy\gis\SAP_IMPORT_SQLARCGIS")
ARCHIVE_PATH = Path(r"\\xxx\yyy\gis\SAP_IMPORT_SQLARCGIS\ARCHIVE)\GISDEVICES")
IMPORT_FILE_NAME = "GISDEVICES.txt"
IMPORT_FILE = WDPath / IMPORT_FILE_NAME
print(IMPORT_FILE, '\n')
# split the file into filename and extension
filename, extension = os.path.splitext(IMPORT_FILE_NAME)
print(filename, extension, '\n')
# Get the create time of the file
create_time = os.path.getctime(IMPORT_FILE)
print(create_time, '\n')
# get the readable timestamp format
## format_time = datetime.datetime.fromtimestamp(create_time)
format_time = date.fromtimestamp(create_time)
print(format_time, '\n')
# convert time into string
format_time_string = format_time.strftime("-%Y-%m-%d")
print(format_time_string, '\n')
# Contruct the new name of the file
newfile = filename + format_time_string + extension
print(newfile, '\n')
# rename the file
IMPORT_FILE.rename(IMPORT_FILE / newfile)
print(IMPORT_FILE)

Related

Python doesn't close the last file

I created this code to get all excel files in a folder and make a csv file to every sheet in every file. This script works fine, but sometimes the last Excel file converted still locked by python on file system. Can anyone help me to understand what's happening?
import sys
from os import listdir
from os.path import isfile, join
import pandas as pd
import csv
import re
def removeEspecialCharacters(obj):
if isinstance(obj, str) :
retorno = re.sub('[(\x90|\x8F)]','',obj).replace("\r","").replace("\n","")
else:
retorno = obj
return retorno
myFolder = r'C:\Users\myuser\Downloads\ConvertFilesToCsv'
myFiles = [f for f in listdir(myFolder) if isfile(join(myFolder, f))]
for x in range(len(myFiles)):
if (myFiles[x].lower().endswith('.xls') or myFiles[x].lower().endswith('.xlsx') or myFiles[x].lower().endswith('.xlsb')):
print('Converting file: '+myFiles[x]);
if (myFiles[x].lower().endswith('.xlsb')):
file = pd.ExcelFile(myFolder+'\\'+myFiles[x], engine='pyxlsb')
else:
file = pd.ExcelFile(myFolder+'\\'+myFiles[x])
for mySheetName in file.sheet_names:
df = pd.read_excel(file, sheet_name=mySheetName)
df = df.applymap(removeEspecialCharacters)
csvFileName = myFolder+'\\'+myFiles[x].replace('.xlsx','').replace('.xlsb','').replace('.xls','')+'_'+mySheetName+'.csv'
df.to_csv(csvFileName,encoding='utf-8-sig',index=False,sep=",",quoting=csv.QUOTE_NONNUMERIC,quotechar="\"",escapechar="\"",decimal=".",date_format='%Y-%m-%d')#,quotechar='\'', escapechar='\\')
file.close()
file = ''
Note: this is a comment putting here for code format.
Your code looks fine to me. I would advise you to use context management, similar to the doc, like this:
for filename in myFiles:
extension = filename.split('.')[-1]
# you didn't seem to check xlsb in your code
if extension not in ['xls', 'xlsx', 'xlsb']:
continue
kwargs = {'engine': 'pyxlsb'} if extension=='xlsb' else {}
with pd.ExcelFile(myFolder + '\\' + filename, **kwargs) as file:
# do other stuff with file
...
# you don't need to close file here
# file.close()

rename files in a folder then move them to another folder

Ive got a bunch of files in a folder all with the same extension:
[movie] Happy feet 2021-04-01 22-00-00.avi
[movie] Dogs Life 2021-06-01 22-03-50.avi
etc
would like to rename the start and end to:
Happy feet.avi
Dogs Life.avi
etc
Here is what I have so far:
import shutil
import os
source_dir = r"C:\\Users\\ED\\Desktop\\testsource"
target_dir = r"C:\\Users\\ED\\Desktop\\testdest"
data = os.listdir(source_dir)
print(data)
new_data = [file[8:].split(' 2021')[0] + '.txt' for file in data]
print(new_data)
for file in data:
os.replace(data, [file[8:].split(' 2021')[0] + '.txt')
for file_name in data:
shutil.move(os.path.join(source_dir, file_name), target_dir)
Im having trouble with the os.rename() part after I printed it out.
You can use (tested):
from glob import glob
import re
import shutil
import os
src = "C:/Users/ED/Desktop/testsource"
dst = "C:/Users/ED/Desktop/testdest"
for f in glob(f"{src}/**"):
fn = os.path.basename(f)
new_fn = re.sub(r"^\[.*?\](.*?) \d{4}-\d{2}-\d{2} \d{2}-\d{2}-\d{2}(\..*?)$", r"\1\2", fn).strip()
shutil.move(f, f"{dst}/{new_fn}")
For python 2:
for f in glob(src+"/**"):
fn = os.path.basename(f)
new_fn = re.sub(r"^\[.*?\](.*?) \d{4}-\d{2}-\d{2} \d{2}-\d{2}-\d{2}(\..*?)$", r"\1\2", fn).strip()
shutil.move(f, dst+"/"+new_fn)
If you're using r"foobar" I don't think you have to escape the \s, do you?
So it should be
source_dir = r"C:\Users\ED\Desktop\testsource"
target_dir = r"C:\Users\ED\Desktop\testdest"
So, there are some issues with the code.
In the for loop for os.replace(), you are passing the entire list of data as src which is ['Dogs Life 2021-06-01 22-03-50.avi', '2021-04-01 22-00-00.avi']
Instead what I did is use file in the loop.
Also with the statement os.replace(data, [file[8:].split(' 2021')[0] + '.txt') your variables inside os.replace() would be a list item, so I changed it string.
One last thing is that you need to use the full file path in the os.move() unless the files are in the current working directory
I didn't touch the shutil.move() function. Let me know if this works.
import shutil
import os
source_dir = r"C:\\Users\\ED\\Desktop\\testsource"
target_dir = r"C:\\Users\\ED\\Desktop\\testdest"
data = os.listdir(source_dir)
print(data)
new_data = [file[8:].split(' 2021')[0] + '.txt' for file in data]
print(new_data)
for file in data:
os.replace('C:\\Users\\ED\\Desktop\\testsource\\'+str(file), 'C:\\Users\\ED\\Desktop\\testsource\\'+str(file[8:].split(' 2021')[0] + '.txt'), src_dir_fd=None, dst_dir_fd=None)

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.

Exporting multiple files with different filenames

Lets say I have n files in a directory with filenames: file_1.txt, file_2.txt, file_3.txt .....file_n.txt. I would like to import them into Python individually and then do some computation on them, and then store the results into n corresponding output files: file_1_o.txt, file_2_o.txt, ....file_n_o.txt.
I've figured out how to import multiple files:
import glob
import numpy as np
path = r'home\...\CurrentDirectory'
allFiles = glob.glob(path + '/*.txt')
for file in allFiles:
# do something to file
...
...
np.savetxt(file, ) ???
Not quite sure how to append the _o.txt (or any string for that matter) after the filename so that the output file is file_1_o.txt
Can you use the following snippet to build the output filename?
parts = in_filename.split(".")
out_filename = parts[0] + "_o." + parts[1]
where I assumed in_filename is of the form "file_1.txt".
Of course would probably be better to put "_o." (the suffix before the extension) in a variable so that you can change at will just in one place and have the possibility to change that suffix more easily.
In your case it means
import glob
import numpy as np
path = r'home\...\CurrentDirectory'
allFiles = glob.glob(path + '/*.txt')
for file in allFiles:
# do something to file
...
parts = file.split(".")
out_filename = parts[0] + "_o." + parts[1]
np.savetxt(out_filename, ) ???
but you need to be careful, since maybe before you pass out_filename to np.savetxt you need to build the full path so you might need to have something like
np.savetxt(os.path.join(path, out_filename), )
or something along those lines.
If you would like to combine the change in basically one line and define your "suffix in a variable" as I mentioned before you could have something like
hh = "_o." # variable suffix
..........
# inside your loop now
for file in allFiles:
out_filename = hh.join(file.split("."))
which uses another way of doing the same thing by using join on the splitted list, as mentioned by #NathanAck in his answer.
import os
#put the path to the files here
filePath = "C:/stack/codes/"
theFiles = os.listdir(filePath)
for file in theFiles:
#add path name before the file
file = filePath + str(file)
fileToRead = open(file, 'r')
fileData = fileToRead.read()
#DO WORK ON SPECIFIC FILE HERE
#access the file through the fileData variable
fileData = fileData + "\nAdd text or do some other operations"
#change the file name to add _o
fileVar = file.split(".")
newFileName = "_o.".join(fileVar)
#write the file with _o added from the modified data in fileVar
fileToWrite = open(newFileName, 'w')
fileToWrite.write(fileData)
#close open files
fileToWrite.close()
fileToRead.close()

How to add prefix to files' names, replace a character, and move to new directory?

For example, the files will look like FG-4.jpg FG-5.jpg, etc. and need to be copied to a new directory and named test_FG_4.jpg test_FG_5.jpg, etc.
Here is the updated code:
import shutil
import glob
import os
InFolder = r"C:\test_in"
OutFolder = r"C:\test_out"
for f in glob.glob('*'):
shutil.move(InFolder/*, OutFolder, copy_function=copy2)
os.listdir(OutFolder)
new_filename = f.replace("-","_")
new_filename = "test_" + new_filename
os.rename(f,new_filename)
I'm getting the error
File "c:\copyRename2.py", line 8, in ?
shutil.move(InFolder/*, OutFolder, copy_function=copy2)
invalid syntax: copyRename2.py, line 8, pos 26 in file c:\copyRename2.py, line 8
shutil.move(InFolder/*, OutFolder, copy_function=copy2)
First attempt:
import shutil
import glob
import os
InFolder = r"C:\test_in"
OutFolder = r"C:\test_out"
for f in glob.glob('*'):
shutil.copyfile(f, OutFolder)
new_filename = f.replace("-","_")
new_filename = "test_" + new_filename
os.rename(f,new_filename)
I am not sure about what you want. So this program checks for any file with extension .jpg and then copies them into a new folder("NewDir") by adding "Test_" to the file name. If the folder doesn't exist, the program creates the folder. Maybe you can make the changes you need based on this program.
import shutil
import os
newdir="NewDir"
for m in (os.listdir()):
if m[-4:]==(".txt"):
if os.path.isdir(newdir):
shutil.copy(m,newdir+"/"+"Test_"+m)
else:
os.mkdir(newdir)
shutil.copy(m,newdir+"/"+"Test_"+m)

Categories