I have folder where I have multiple files. Out of this files I want to rename some of them. For example: PB report December21 North.xlsb, PB report November21 North.xslb and so on. They all have a same start - PB report. I would like to change their name and leave only PB report and Month. For example PB report December.
I have tried this code:
import os
path = r'C://Users//greencolor//Desktop//Autoreport//Load_attachments//'
for filename in os.listdir(path):
if filename.startswith("PB report"):
os.rename(filename, filename[:-8])
-8 indicates that I want to split the name from the end on the 8th character
I get this error:
FileNotFoundError: [WinError 2] The system cannot find the file specified
Any suggestion?
You need the path when renaming file with os.rename:
Replace:
os.rename(filename, filename[:-8])
With:
filename_part, extension = os.path.splitext(filename)
os.rename(path+filename, path+filename_part[:-8]+extension)
The problem is likely that it cannot find the file because the directory is not specified. You need to add the path to the file name:
import os
path = r'C://Users//greencolor//Desktop//Autoreport//Load_attachments//'
for filename in os.listdir(path):
if filename.startswith("PB report"):
os.rename(os.path.join(path, filename), os.path.join(path, filename[:-8]))
This is a classic example of how working with os/os.path to manipulate paths is just not convenient. This is why pathlib exists. By treating paths as objects, rather than strings everything becomes more sensible. By using a combination of path.iterdir() and path.rename() you can achieve what you want like:
from pathlib import Path
path = Path(r'your path')
for file in path.iterdir():
if file.name.startswith("PB report"):
file.rename(file.with_stem(file.stem[:-8]))
Note that stem means the filename without the extension and that with_stem was added in Python 3.9. So for older versions you can still use with_name:
file.rename(file.with_name(file.stem[:-8] + file.suffix))
Where suffix is the extension of the file.
Related
I'm working with python and I need to rename the files that I have inside a directory for example:
C:\Users\lenovo\Desktop\files\file1.txt
C:\Users\lenovo\Desktop\file\file2.txt
C:\Users\lenovo\Desktop\files\file3.txt
I have these 3 files inside the files folder, and I want to change the name of these, I have my script inside another folder: C:\Users\lenovo\Desktop\app\rename.py
I don't know if this is the problem but this is what I tried and it didn't work for me:
import os
directory = r'C:\Users\lenovo\Desktop\files'
count=0
for filename in os.listdir(directory):
count +=1
f = os.path.join(directory, filename)
if os.path.isfile(f):
os.rename(f, "new_file"+str(count))
UPDATE
the code simply deletes the original files and tries to create others inside the folder where I have the python script.
You need to prepend the directory to the new files
import os
directory = r'C:\Users\lenovo\Desktop\files'
count=0
for filename in os.listdir(directory):
count +=1
f = os.path.join(directory, filename)
new_f = os.path.join(directory, "new_file"+str(count)+".txt")
if os.path.isfile(f):
os.rename(f, new_f)
In general, when in doubt, it's best to use long/absolute path names when renaming/moving files. If you want to rename a file in its current directory, use the full path name in the target file name, as well. So, try changing the line:
os.rename(f, "new_file"+str(count))
to:
os.rename(f, os.path.join(directory, "new_file"+str(count)))
This absolute path will rename each file in its original directory. Otherwise, as you've experienced, relative file names are treated as relative to the directory of the executable.
Once you do the above, you'll probably want to do more tweaks to get a better result, but this should get you closer to your objective.
You used a relative path for the target filename, so the operating system based the path on the current working directory. That CWD was also your script path hints that you ran the program from your script path.
You could use os.path.join to make the path relative to your target directory. But you could also use pathlib
from pathlib import Path
directory = Path(r'C:\Users\lenovo\Desktop\files')
count = 0
for target in Path.iterdir():
if target.is_file():
target.replace(directory/f"newfile{count}")
count += 1
I am trying to remove special character(-) from multiple files in folder.
Example:
Filenames :
-name1.xml
-name2.xml
-name3.xml
Rename To:
name1.xml
name2.xml
name3.xml
My Code :
import os
for filename in os.listdir(Folder):
os.rename(Folder+'/'+filename, Folder + '/' + Filename.replace("-","" )
but Unfortunately it appears to do nothing.
How do I do this properly?
In the code below, you can simply use the replace function to get your desired output. Let me know if this works and/or helps!
import os
# I named my folder containing .XML files "Test"
Folder = 'Test/'
for filename in os.listdir(Folder):
os.rename(Folder + filename, Folder + filename.replace('-',''))
Outputs:
name1.xml
name2.xml
name3.xml
I am a big fan of using Pathlib for problems like this.
Given (on Unix but should work on all OSs):
% ls -1
-name1.xml
-name2.xml
-name3.xml
name-4.xml
You can do:
from pathlib import Path
p=Path(Folder)
for fn in p.glob("-*.xml"):
fn.replace(fn.with_name(str(fn.name).replace('-','')))
Result:
% ls -1
name-4.xml
name1.xml
name2.xml
name3.xml
The glob -*.xml only will find files that start with - so the file name-4.xml is unchanged.
Pathlib (as written here) will also work the same regardless of the path separator on different OSs.
I am playing around with some python scripts and I ran into a problem with the script I'm writing. It's supposed to find all the files in a folder that meets the criteria and then delete it. However, it finds the files, but at the time of deleting the file, it says that the file is not found.
This is my code:
import os
for filename in os.listdir('C:\\New folder\\'):
if filename.endswith(".rdp"):
os.unlink(filename)
And this is the error I get after running it:
FileNotFoundError: [WinError 2] The system cannot find the file specified:
Can somebody assist with this?
os.unlink takes the path to the file, not only its filename. Try pre-pending your filename with the dirname. Like this
import os
dirname = 'C:\\New folder\\'
for filename in os.listdir(dirname):
if filename.endswith(".rdp"):
# Add your "dirname" to the file path
os.unlink(dirname + filename)
You could alternatively use os.walk, however it might go deeper than you want:
import os
for root, sub, file in os.walk("/media/"):
if file.endswith(".rdp"):
os.unlink(f'{root}/{file}')
I have the below files located at some location in RHEL machine.
temp_file2.txt
temp_file3.txt
Looking for a python script to find above files recursively in all directories(I used a wild card, but it didn't work), and print a message if the file exists or not.
The below code snippet returns Nothing
import glob
for filename in glob.iglob('*/*.txt', recursive=True):
print(filename)
It returns the file name if it exists only in the current working directory
import glob
for filename in glob.iglob('.txt', recursive=True):
print(filename)
This approach seems to have worked for me, using python3.6
import glob
for f in glob.iglob('./**/*.yml', recursive=True):
print(f)
I was also able to use os.getcwd() + '/**/*.yml'. It appears there must be a directory definition at the start of the glob.
EDIT: ANSWER Below is the answer to the question. I will leave all subsequent text there just to show you how difficult I made such an easy task..
from pathlib import Path
import shutil
base = "C:/Users/Kenny/Documents/Clients"
for file in Path("C:/Users/Kenny/Documents/Scans").iterdir():
name = file.stem.split('-')[0].rstrip()
subdir = Path(base, name)
if subdir.exists():
dest = Path(subdir, file.name)
shutil.move(file, dest)
Preface:
I'm trying to write code that will move hundreds of PDF files from a :/Scans folder into another directory based on the matching client's name. This question is linked below - a very kind person, Elis Byberi, helped assist me in correcting my original code. I'm encountering another problem though..
To see our discussion and a similar question discussed:
-Python- Move All PDF Files in Folder to NewDirectory Based on Matching Names, Using Glob or Shutil
Python move files from directories that match given criteria to new directory
Question: How can you move all of the named files in :/Scans to their appropriately matched folder in :/Clients.
Background: Here is a breakdown of my file folders to give you a better idea of what I'm trying to do.
Within :/Scans folder I have thousands of PDF files, manually renamed (I tried writing a program to auto-rename.. didn't work) based on client and content, such that the folder encloses PDFs labeled as follows:
lastName, firstName - [contentVariable]
(repeat the above 100,000x)
Within the :/C drive of my computer I have a folder named 'Clients' with sub-folders for each and every client, named similar to the pattern above, as 'lastName, firstName'
EDIT: The code below will move the entire Scans folder to the Clients folder, which is close, but not exactly what I need to be doing. I only need to move the files within Scans to the corresponding Client fold names.
import glob
import shutil
import os
source = "C:/Users/Kenny/Documents/Scans"
dest = "C:/Users/Kenny/Documents/Clients"
os.chdir("C:/Users/Kenny/Documents/Clients")
pattern = '*,*'
for x in glob.glob(pattern):
fileName = os.path.join(source, x)
print(fileName)
shutil.move(source, dest)
EDIT 2 - CLOSE!: The code below will move all the files in Scans to the Clients folder, which is close, but not exactly what I need to be doing. I need to get each file into the correct corresponding file folder within the Clients folder.
This is a step forward from moving the entire Scans folder I would think.
source = "C:/Users/Kenny/Documents/Scans"
dest = "C:/Users/Kenny/Documents/Clients"
for (dirpath, dirnames, filenames) in walk(source):
for file in filenames:
shutil.move(path.join(dirpath,file), dest)
I have the following code below as well, and I am aware it does not do what I want it to do, so I am definitely missing something..
import glob
import shutil
import os
path = "C:/Users/Kenny/Documents/Scans"
dirs = os.listdir(path)
for file in dirs:
print(file)
dest_dir = "C:/Users/Kenny/Documents/Clients/{^w, $w}?"
for file in glob.glob(r'C:Users/Kenny/Documents/Clients/{^w, $w}?'):
print(file)
shutil.move(file, dest_dir)
1) Should I use os.scandir instead of os.listdir ?
2) Am I moving in the correct direction if I modify the code as such:
import glob
import shutil
import os
path = "C:/Users/Kenny/Documents/Scans"
dirs = os.scandir(path)
for file in dirs:
print(file)
dest_dir = "C:/Users/Kenny/Documents/Clients/*"
for file in glob.glob(r'C:Users/Kenny/Documents/Clients, *'):
dest_dir = os.path.join(file, glob.glob)
shutil.move(file, dest_dir)
Note within the 'for file in glob.glob(r'C:Users/Kenny/Documents/Clients/{^w, $w}?' I have tried replacing 'Clients/{^w, $w}?' with just 'Clients/*'
For the above, I only need the file in :/Scans, written as, "lastName, firstName - [content]" to be matched and moved to /Clients/[lastName, firstName] --- the [content] does not matter. But there are both greedy and nongreedy expressions... which is why I'm unsure about using * or {^w, $w}? -- because we have clients with the same last names, but different first names.
The following error is generated when running the first command:
Error 1
Error 2
The following error (though, there is no error?) is generated when running the second command:
Error 3
EDIT/POSSIBLE ANSWER
Have not yet tested this but, fnmatch(filename, pattern), or, fnmatch.translate(pattern) can be used to test whether the filename string matches the pattern string, returning True or False.
From here perhaps you could write a conditional statement..
for file in os.listdir('.'):
if fnmatch.fnmatch(file, '*.txt'):
shutil.move(source, destination)
or
for file in os.listdir('.'):
if fnmatch.fnmatch(file, '*.txt'):
shutil.move(file.join(eachFile, source), destination)
I have not tested the two aforesaid codes. I have no idea if they work, but editing allows others to see how my train of thought is progressing.