Recursively rename files in python [duplicate] - python

This question already has answers here:
Rename multiple files in a directory in Python
(15 answers)
Closed 3 years ago.
I have a folder named '12' and this folder contains following files:
import os
for root, dirs, files in os.walk('./12', topdown=True):
dirs.clear() #with topdown true, this will prevent walk from going into subs
for file in files:
print(file)
Output:
ab 1.jpg
ab 0.jpg
Now I want to replace spaces in the above files with an underscore to do this I have done:
import os
for root, dirs, files in os.walk('./12', topdown=True):
dirs.clear() #with topdown true, this will prevent walk from going into subs
for file in files:
r=file.replace(" ", "_")
os.rename(r, file)
In the above code when I print(r) it gives me value of space replaced by underscore i.e
ab__1.jpg
ab_0.jpg
But the os.rename function does not work and actual file names are not changed inside the folder. I get the following error for os.rename(r, file):
Traceback (most recent call last): File "demo.py", line 7, in
os.rename(r, file) FileNotFoundError: [Errno 2] No such file or directory: 'ab__1.jpg' -> 'ab 1.jpg'
How can I resolve this error ?
Edit:
My question is not a duplicate of Rename multiple files in a directory in Python because on the mentioned link they are using one for loop to recursively rename all the files in the current working directory. In my question I am using 2 for loops as renaming files is one sub part of my entire process, When I use two for loops I am encountering my error.

Perhaps you are intending to do os.rename("./12/" + file, ./12/" + r)? As you are modifying the files in the directory named 12, not the directory where the Python script was executed from.

My bad I had to provide absolute path to rename these files:
import os
cwd=os.getcwd()+'/12'
print(cwd)
for root, dirs, files in os.walk('./12', topdown=True):
dirs.clear() #with topdown true, this will prevent walk from going into subs
for file in files:
r=file.replace(" ", "_")
os.rename(os.path.join(cwd,file), os.path.join(cwd,r))

Use os.rename(file, r) instead of os.rename(r, file).

Related

Python: Finding files in directory but ignoring folders and their contents

So my program search_file.py is trying to look for .log files in the directory it is currently placed in. I used the following code to do so:
import os
# This is to get the directory that the program is currently running in
dir_path = os.path.dirname(os.path.realpath(__file__))
# for loop is meant to scan through the current directory the program is in
for root, dirs, files in os.walk(dir_path):
for file in files:
# Check if file ends with .log, if so print file name
if file.endswith('.log')
print(file)
My current directory is as follows:
search_file.py
sample_1.log
sample_2.log
extra_file (this is a folder)
And within the extra_file folder we have:
extra_sample_1.log
extra_sample_2.log
Now, when the program runs and prints the files out it also takes into account the .log files in the extra_file folder. But I do not want this. I only want it to print out sample_1.log and sample_2.log. How would I approach this?
Try this:
import os
files = os.listdir()
for file in files:
if file.endswith('.log'):
print(file)
The problem in your code is os.walk traverses the whole directory tree and not just your current directory. os.listdir returns a list of all filenames in a directory with the default being your current directory which is what you are looking for.
os.walk documentation
os.listdir documentation
By default, os.walk does a root-first traversal of the tree, so you know the first emitted data is the good stuff. So, just ask for the first one. And since you don't really care about root or dirs, use _ as the "don't care" variable name
# get root files list.
_, _, files = next(os.walk(dir_path))
for file in files:
# Check if file ends with .log, if so print file name
if file.endswith('.log')
print(file)
Its also common to use glob:
from glob import glob
dir_path = os.path.dirname(os.path.realpath(__file__))
for file in glob(os.path.join(dir_path, "*.log")):
print(file)
This runs the risk that there is a directory that ends in ".log", so you could also add a testing using os.path.isfile(file).

How to move and enter folders and subfolders in python [duplicate]

This question already has answers here:
Using os.walk() to recursively traverse directories in Python
(14 answers)
Closed 2 years ago.
i have a dataset and one folder and in this folder i have a few subfolder in them there is audio file i need to move on the whole subfolders and get the file and the path , i using python
osomeone has idea?
folder: dataset -> folders: rock,regge,hiphop,classic,disco,jazz,pop,blues,country,metal -> files: "name".wav
i need to enter each folder and get the file and path.
i have 100 files in folder.
i dont try nothing because i dont know how to do that
You should use os.walk
import os
for subdir, dirs, files in os.walk(rootdir):
for file in files:
filepath = subdir + os.sep + file
if filepath.endswith(".wav"):
print(filepath)

os.listdir not listing files in directory

For some reason os.listdir isn't working for me. I have 6 .xlsx files inside the input_dir but it creating a list with nothing in it instead of showing a list of 6 files. If I move the .xlsx files into where the script is one directory back, and update the input_dir path it then finds all 6 files but I need the 6 files to be one directory up in their own folder. And when I move them one directory up into their own folder, and I update the input_dir path it doesn't find them at all.
import openpyxl as xl
import os
import pandas as pd
import xlsxwriter
input_dir='C:\\Users\\work\\comparison'
files = [file for file in os.listdir(input_dir)
if os.path.isfile(file) and file.endswith(".xlsx")]
for file in files:
input_file = os.path.join(input_dir, file)
wb1=xl.load_workbook(input_file)
ws1=wb1.worksheets[0]
When you move the files into input_dir, the following line creates an empty list:
files = [file for file in os.listdir(input_dir)
if os.path.isfile(file) and file.endswith(".xlsx")]
This is because you are checking for os.path.isfile(file) instead of os.path.isfile(os.path.join(input_dir, file))
When files are present in the same directory as the script, it's able to find the file and creates the list correctly.
Alternatively, you could try using glob.glob which accepts a file path pattern and returns full path to the file in the iterator.
The problem comes from os.path.isfile(file) : os.listdir(input_dir) returns a list of filenames inside the input_dir directory, but without their path. Hence your error, as os.path.isfile(file) will look into your current directory, which obviously doesn't have any of those filenames.
You can easily correct this by simply changing os.path.isfile(input_dir + '\\' + file), but a prettier solution would rather be to simply delete this part of the code (as if os.listdir returns this filename, then it is necessary into your directory and there's no need to check if so) :
files = [file for file in os.listdir(input_dir) if file.endswith(".xlsx")]

Renaming Files in Python, Getting FileNotFoundError [duplicate]

I am trying to write a program to categorize into folders a large amount of files according to their respective groups indicated in the file name. I wrote the followin code, but when I run it it gives me a file not found error, even though the file is in the given path. I'd appreciate any help in figuring out what is wrong.
import os
old_dir = '/Users/User/Desktop/MyFolder'
for f in os.listdir(old_dir):
file_name, file_ext = os.path.splitext(f)
file_name.split('-')
split_file_name = file_name.split('-')
new_dir = os.path.join(old_dir,
'-'.join(split_file_name[:3]),
split_file_name[5],
f)
os.rename(os.path.join(old_dir, f), new_dir)
Here's the error:
Traceback (most recent call last):
File "/Users/User/Documents/Sort Files into Folders/Sort Files into Folders.py", line 19, in <module>
os.rename(os.path.join(old_dir, f), new_dir)
FileNotFoundError: [Errno 2] No such file or directory: '/Users/User/Desktop/MyFolder/AHA35-3_30x1_12-31-7d-g1a1-ArmPro.jpg' -> '/Users/User/Desktop/MyFolder/AHA35-3_30x1_12-31/ArmPro/AHA35-3_30x1_12-31-7d-g1a1-ArmPro.jpg
os.rename does not automatically create new directories (recursively), if the new name happens to be a filename in a directory that does not exist.
To create the directories first, you can (in Python 3) use:
os.makedirs(dirname, exist_ok=True)
where dirname can contain subdirectories (existing or not).
Alternatively, use os.renames, that can handle new and intermediate directories. From the documentation:
Recursive directory or file renaming function. Works like rename(), except creation of any intermediate directories needed to make the new pathname good is attempted first
os.rename need path, so it should look like:
os.rename(path+old_name, path+new_name)

iterate a directory and find only file whose names start with the certain string

I have a directory path and in this path there are several folders. So i am am trying to build a script which would find all the xml files and the file name must start with report. I have been so far able to iterate over all the directories but further i do not know how to proceed. Here is my code:
def search_xml_report(rootdir):
for subdir, dirs, files in os.walk(rootdir):
for file in files:
print os.path.join(subdir,file) # print statement just for testing
You can use str.startswith:
def search_xml_report(rootdir):
for subdir, dirs, files in os.walk(rootdir):
for file in files:
if file.startswith('report'):
yield subdir, file
use str.startswith with os.path.splitext
os.path.splitext: Split the extension from a pathname. Extension is everything from the last dot to the end, ignoring leading dots. Returns "(root, ext)"; ext may be empty.
if file.startswith('report') and os.path.splitext(filepath+filename)[-1] == '.xml':
return file

Categories

Resources