Renaming files and folders with the os.walk in Python 3 - python

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))

Related

rename files inside another directory in python

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

Working with file directories and variables

I have a program that I want to make more dynamic. The current setup is literally typing everything out.
I would like the program to work with a for loop (any other suggestions would be great). My goal is to loop through a specific file that has sub-directories and get the name of each folder (sub-directory), then get the name of the files within the sub-directory.
To put this in a file string:
C:\Folder 1\Folder 2\File name
From the above, I would like to get the value of Folder 2 and File name.
My code so far:
for sub_dir in os.listdir(r"C:\Folder 1\"):
DIR = r'' + sub_dir
files_found = len([name for name in os.listdir(DIR) if os.path.isfile(os.path.join(DIR, name))])
if(files_found > 0):
for files in os.listdir(sub_dir):
file_name = os.path.splitext(files)[0]
I get the error --> FileNotFoundError: [WinError 3] The system cannot find the path specified: Folder 2
I appreciate your efforts to help.
You should take a look at os.walk
Have a look at os.walk()
It recursively traverses a file tree, returning a list of all directories and files within a directory at each step.

Removing randomly generated file extensions from .jpg files using python

I recently recovered a folder that i had accidentally deleted. It has .jpg and .tar.gz files. However, all of the files now have some sort of hash extension appended to them and it is different for every file. There are more than 600 files in the folders. So example names would be:
IMG001.jpg.3454637876876978068
IMG002.jpg.2345447786787689769
IMG003.jpg.3454356457657757876
and
folder1.tar.gz.45645756765876
folder2.tar.gz.53464575678588
folder3.tar.gz.42345435647567
I would like to have a script that could go in turn (maybe i can specify extension or it can have two iterations, one through the .jpg files and the other through the .tar.gz) and clean up the last part of the file name starting from the . right before the number. So the final file names would end in .jpg and .tar.gz
What I have so far in python:
import os
def scandirs(path):
for root, dirs, files in os.walk(path):
for currentFile in files:
os.path.splitext(currentFile)
scandirs('C:\Users\ad\pics')
Obviously it doesn't work. I would appreciate any help. I would also consider using a bash script, but I do not know how to do that.
shutil.move(currentFile,os.path.splitext(currentFile)[0])
at least I think ...
Here is how I would do it, using regular expressions:
import os
import re
pattern = re.compile(r'^(.*)\.\d+$')
def scandirs(path):
for root, dirs, files in os.walk(path):
for currentFile in files:
match = pattern.match(currentFile)
if match:
os.rename(
os.path.join(root, currentFile),
os.path.join(root, match.groups(1)[0])
)
scandirs('C:/Users/ad/pics')
Since you tagged with bash I will give you an answer that will remove the last extension for all files/directories in a directory:
for f in *; do
mv "$f" "${f%.*}"
done

First Practice Project in Automate the Boring Stuff with Python, Ch. 9

So my friend and I have been having a problem with the first practice project of the above chapter of Automate the Boring Stuff with Python. The prompt goes: "Write a program that walks through a folder tree and searches for files with a certain file extension (such as .pdf or .jpg). Copy these files from whatever location they are in to a new folder."
To simplify, we are trying to write a program that copies all of the .jpg files out of My Pictures to another directory. Here's our code:
#! python3
# moveFileType looks in My Puctures and copies .jpg files to my Python folder
import os, shutil
def moveFileType(folder):
for folderName, subfolders, filenames in os.walk(folder):
for subfolder in subfolders:
for filename in filenames:
if filename.endswith('.jpg'):
shutil.copy(folder + filename, '<destination>')
moveFileType('<source>')
We keep getting an error along the lines of "FileNotFoundError: [Errno 2] No such file or directory".
Edit: I added a "\" to the end of my source path (I'm not sure if that is what you meant, #Jacob H), and was able to copy all of the .jpg files in that directory, but received an error when it tried to copy a file within a subfolder of that directory. I added a for loop for subfolder in subfolders and I no longer get any errors, but it doesn't actually look in the subfolders for .jpg files.
There is a more fundamental problem with your code. When you use os.walk() it will already loop through every directory for you, so looping manually through the subfolders is going to produce the same results multiple times.
The other, and more immediate, problem is that os.walk() produces relative file names, so you need to glue them back together. Basically you are omitting the directory name and looking in the current directory for files which os.walk() is finding down in a subdirectory somewhere.
Here's a quick attempt at fixing your code:
def moveFileType(folder):
for folderName, subfolders, filenames in os.walk(folder):
for filename in filenames:
if filename.endswith('.jpg'):
shutil.copy(os.path.join(folderName, filename), '<destination>')
Making the function accept a destination parameter as a second argument, instead of hardcoding <destination>, would make it a lot more useful for the future.
Make sure to type the source file destination address correctly. While i tested your code, i wrote
moveFileType('/home/anum/Pictures')
and i got error;
IOError: [Errno 2] No such file or directory:
and when i wrote
moveFileType('/home/anum/Pictures/')
the code worked perfectly...
Try doing that, hope that will do your work. M using Python 2.7
Herez the re defined code for walking into subfolders and copying ,jpg files from there aswell.
import os, shutil
def moveFileType(folder):
for root, dirs, files in os.walk(folder):
for file in files:
if file.endswith('.jpg'):
image_path=os.path.join(root,file) # get the path location of each jpeg image.
print 'location: ',image_path
shutil.copy(image_path, '/home/anum/Documents/Stackoverflow questions')
moveFileType('/home/anum/Pictures/')

Python - Present all files within a specific folder without the given folder

Using Python, I want to print all the files inside a given directory, without display the directory itself. I tried to use os.walk but it always print the directory.
for root, dirs, files in os.walk(directory):
for subFile in files:
print os.path.join(root, subFile)
I used the directory 'DummyFolder/testFolder'
It prints:
DummyFolder/testFolder/folder1/folder2/file.txt
DummyFolder/testFolder/folder1/folder2/file2.txt
DummyFolder/testFolder/folder3/file3.txt
I want it to print:
folder1/folder2/file.txt
folder1/folder2/file2.txt
folder3/file3.txt
How can it be done?
Thanks!
Use os.path.relpath to get path relative to your directory.
print(os.path.relpath(os.path.join(root, subFile), directory))

Categories

Resources