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
Related
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.
I am trying to zip all the files and folders present in a folder3 using python.
I have used zipFile for this. The zip contains all the folders from the root directory to the directory I want to create zip folder of.
def CreateZip(dir_name):
os.chdir(dir_name)
zf = zipfile.ZipFile("temp.zip", "w")
for dirname, subdirs, files in os.walk(dir_name):
zf.write(dirname)
for filename in files:
file=os.path.join(dirname, filename)
zf.write(file)
zf.printdir()
zf.close()
Expected output:
toBeZippedcontent1\toBeZippedFile1.txt
toBeZippedcontent1\toBeZippedFile2.txt
toBeZippedcontent1\toBeZippedFile1.txt
toBeZippedcontent2\toBeZippedFile2.txt
Current output (folder structure inside zip file):
folder1\folder2\folder3\toBeZippedcontent1\toBeZippedFile1.txt
folder1\folder2\folder3\toBeZippedcontent1\toBeZippedFile2.txt
folder1\folder2\folder3\toBeZippedcontent2\toBeZippedFile1.txt
folder1\folder2\folder3\toBeZippedcontent2\toBeZippedFile2.txt
walk() gives absolute path for dirname so join() create absolut path for your files.
You may have to remove folder1\folder2\folder3 from path to create relative path.
file = os.path.relpath(file)
zf.write(file)
You could try to slice it
file = file[len("folder1\folder2\folder3\\"):]
zf.write(file)
but relpath() should be better.
You can also use second argument to change path/name inside zip file
z.write(file, 'path/filename.ext')
It can be useful if you run code from different folder and you don't use os.chdir() so you can't create relative path.
I am trying to rename all files and folders in a given directory. Id like to replace a space with a hyphen and then rename all to lowercase. I am stuck with the code below. When os.rename is commented out, the print function returns all files as expected, however when I uncomment os.rename I get an error stating that file XYZ -> x-y-z cant be found.
import os
folder = r"C:\Users\Tim\Documents\storage"
space = " "
hyphen = "-"
for root, dirs, files in os.walk(folder):
for file in files:
if space in file:
newFilename = filename.replace(space, hyphen).lower()
os.rename(file, newFilename)
print(newFilename)
Obvioulsy this is just for the files but I'd like to apply the same logic to folders too. Any help would be greately appreciated. Pretty new at Python so this is a little beyond me! Thanks so much.
os.rename() resolves relative file paths (paths that doesn't start with a / in Linux/Mac or a drive letter in Windows) relative to the current working directory.
You'll want to os.path.join() the names with root before passing it to os.rename(), as otherwise rename would look for the file with that name in the current working directory instead of in the original folder.
So it should be:
os.rename(os.path.join(root, file), os.path.join(root, newFilename))
I am trying to create a program that copies files with certain file extension to the given folder. When files are located in subfolders instead of the root folder the program fails to get correct path. In its current state the program works perfectly for the files in the root folder, but it crashes when it finds matching items in subfolders. The program tries to use rootfolder as directory instead of the correct subfolder.
My code is as follows
# Selective_copy.py walks through file tree and copies files with
# certain extension to give folder
import shutil
import os
import re
# Deciding the folders and extensions to be targeted
# TODO: user input instead of static values
extension = "zip"
source_folder = "/Users/viliheikkila/documents/kooditreeni/"
destination_folder = "/Users/viliheikkila/documents/test"
def Selective_copy(source_folder):
# create regex to identify file extensions
mo = re.compile(r"(\w+).(\w+)") # Group(2) represents the file extension
for dirpath, dirnames, filenames in os.walk(source_folder):
for i in filenames:
if mo.search(i).group(2) == extension:
file_path = os.path.abspath(i)
print("Copying from " + file_path + " to " + destination_folder)
shutil.copy(file_path, destination_folder)
Selective_copy(source_folder)
dirpath is one of the things provided by walk for a reason: it gives the path to the directory that the items in files is located in. You can use that to determine the subfolder you should be using.
file_path = os.path.abspath(i)
This line is blatantly wrong.
Keep in mind that filenames keeps list of base file names. At this point it's just a list of strings and (technically) they are not associated at all with files in filesystem.
os.path.abspath does string-only operations and attempts to merge file name with current working dir. As a result, merged filename points to file that does not exist.
What should be done is merge between root and base file name (both values yield from os.walk):
file_path = os.path.abspath(dirpath, i)
I'm doing a Python course on Udacity. And there is a class called Rename Troubles, which presents the following incomplete code:
import os
def rename_files():
file_list = os.listdir("C:\Users\Nick\Desktop\temp")
print (file_list)
for file_name in file_list:
os.rename(file_name, file_name.translate(None, "0123456789"))
rename_files()
As the instructor explains it, this will return an error because Python is not attempting to rename files in the right folder. He then proceeds to check the "current working directory", and then goes on to specify to Python which directory to rename files in.
This makes no sense to me. We are using the for loop to specifically tell Python that we want to rename the contents of file_list, which we have just pointed to the directory we need, in rename_files(). So why does it not attempt to rename in that folder? Why do we still need to figure out cwd and then change it?? The code looks entirely logical without any of that.
Look closely at what os.listdir() gives you. It returns only a list of names, not full paths.
You'll then proceed to os.rename one of those names, which will be interpreted as a relative path, relative to whatever your current working directory is.
Instead of messing with the current working directory, you can os.path.join() the path that you're searching to the front of both arguments to os.rename().
I think your code needs some formatting help.
The basic issue is that os.listdir() returns names relative to the directory specified (in this case an absolute path). But your script can be running from any directory. Manipulate the file names passed to os.rename() to account for this.
Look into relative and absolute paths, listdir returns names relative to the path (in this case absolute path) provided to listdir. os.rename is then given this relative name and unless the app's current working directory (usually the directory you launched the app from) is the same as provided to listdir this will fail.
There are a couple of alternative ways of handling this, changing the current working directory:
os.chdir("C:\Users\Nick\Desktop\temp")
for file_name in os.listdir(os.getcwd()):
os.rename(file_name, file_name.translate(None, "0123456789"))
Or use absolute paths:
directory = "C:\Users\Nick\Desktop\temp"
for file_name in os.listdir(directory):
old_file_path = os.path.join(directory, file_name)
new_file_path = os.path.join(directory, file_name.translate(None, "0123456789"))
os.rename(old_file_path, new_file_path)
You can get a file list from ANY existing directory - i.e.
os.listdir("C:\Users\Nick\Desktop\temp")
or
os.listdir("C:\Users\Nick\Desktop")
or
os.listdir("C:\Users\Nick")
etc.
The instance of the Python interpreter that you're using to run your code is being executed in a directory that is independent of any directory for which you're trying to get information. So, in order to rename the correct file, you need to specify the full path to that file (or the relative path from wherever you're running your Python interpreter).