Renaming multiple sub folders to match the parent folder's name - python

I'm a python beginner but have some basic experience, and I need someone to please help me use the os module to rename sub folders based on their parent folder. I've been searching for answers for the past week and have not had any success. I'm assuming I need to use the os.walk method to do this.
Here is my folder structure:
C:\data\test\
C:\data\test\map1
C:\data\test\map1\1617151
C:\data\test\map2
C:\data\test\map2\181719
C:\data\test\map3
C:\data\test\map3\182726
C:\data\test\map4
C:\data\test\map4\894932
I need the results to look like this.
C:\data\test\
C:\data\test\map1
C:\data\test\map1\map1
C:\data\test\map2
C:\data\test\map2\map2
C:\data\test\map3
C:\data\test\map3\map3
C:\data\test\map4
C:\data\test\map4\map4
Can someone please help?

python 2.7:
import os
os.chdir("C:\data\test\") # go to dir
sub_dirs = os.walk('.').next()[1] # get list of subdirs
for sub_dir in sub_dirs:
sub_sub_dir = os.walk('.').next[1] # get sub-subdir
os.rmdir(sub_sub_dir) # remove sub-subdir
os.makedirs(sub_dir + '\bla') # make new sub-subdir named subdir\bla
python 3+:
import os
os.chdir("C:\data\test\")
sub_dirs=next(os.walk('.'))[1]
for sub_dir in sub_dirs:
sub_sub_dir = next(os.walk('.'))[1]
os.rmdir(sub_sub_dir)
os.makedirs(sub_dir + '\bla')
Untested, but should do it.

You can get a list of all the files and it's respective folder location using this one liner:
here = '.' # Current location
files = [(root, files) for root, dirs, files in os.walk(here) if (not dirs and files)]
For the given folder structure it will return:
[
('C:\data\test\map1', ['1617151']),
...
]
You can now loop over this list and rename the files (https://docs.python.org/3/library/os.html#os.rename). You can get the parent folder's name by splitting the root string (root.split('\')[-1]).

Related

How to rename subfolders by numerical pattern and order based on theirs parent in python

I have a folder with many sub-folders, and each sub-folder also has two sub-folders. The structure looks like this:
--folder
--sub-f1
--1-1000
--1-1050
--sub-f2
--1-1030
--1-1060
--sub-f3
--1-1040
--1-1070
What I want to achieve is extract the folder with smaller number in name(in the above example, 1-1000, 1-1030 and 1-1040) and rename these folders according to their parent folders(sub-f1-1, sub-f2-1 and sub-f3-1). I'm running Windows 10 and any simple solutions are welcome!
I have written a fairly verbose algorithm to explain step by step how it works:
from glob import glob
import os
root_dir = 'folder' # specify here your root dir, in your example is "folder"
parent_dirs = glob(f"{root_dir}/*", recursive=True) # detect all first level subdirs
for parent in parent_dirs:
# for each parent dirs, detect all childs
child_dirs = glob(f"{parent}/*", recursive=True)
# for each child, extract the last part of name (e.g. 1000) and append to list
child_nums = []
for child in child_dirs:
child_nums.append(child.split(os.sep)[-1].split("-")[-1])
# find smallest child num and its index in list to retrieve corrispondent full path
small_child = min(child_nums)
small_child_index = child_nums.index(small_child)
src_folder = child_dirs[small_child_index]
# compose the destination dir name
dst_folder = os.path.join(parent, parent.split(os.sep)[1] + "-1")
os.rename(src_folder, dst_folder)
print(f"src_folder '{src_folder}' renamed as: '{dst_folder}'")
output will be:
src_folder 'folder\sub-f1\1-1000' renamed as: 'folder\sub-f1\sub-f1-1'
src_folder 'folder\sub-f2\1-1030' renamed as: 'folder\sub-f2\sub-f2-1'
src_folder 'folder\sub-f3\1-1040' renamed as: 'folder\sub-f3\sub-f3-1'
This solution can be implemented in many other ways, even without using glob and just using os.walk() for example. You can use much more optimized algorithms but it depends on how many folders you need to rename. This is just a simple example.

Python get all the file name in a list

The problem is to get all the file names in a list that are under a particular directory and in a particular condition.
We have a directory named "test_dir".
There, we have sub directory "sub_dir_1", "sub_dir_2", "sub_dir_3"
and inside of each sub dir, we have some files.
sub_dir_1 has files ['test.txt', 'test.wav']
sub_dir_2 has files ['test_2.txt', 'test.wav']
sub_dir_2 has files ['test_3.txt', 'test_3.tsv']
What I want to get at the end of the day is a list of of the "test.wav" that exist under the "directory" ['sub_dir_1/test.wav', 'sub_dir_2/test.wav']. As you can see the condition is to get every path of 'test.wav' under the mother directory.
mother_dir_name = "directory"
get_test_wav(mother_dir_name)
returns --> ['sub_dir_1/test.wav', 'sub_dir_2/test.wav']
EDITED
I have changed the direction of the problem.
We first have this list of file names
["sub_dir_1/test.wav","sub_dir_2/test.wav","abc.csv","abc.json","sub_dir_3/test.json"]
from this list I would like to get a list that does not contain any path that contains "test.wav" like below
["abc.csv","abc.json","sub_dir_3/test.json"]
You can use glob patterns for this. Using pathlib,
from pathlib import Path
mother_dir = Path("directory")
list(mother_dir.glob("sub_dir_*/*.wav"))
Notice that I was fairly specific about which subdirectories to check - anything starting with "sub_dir_". You can change that pattern as needed to fit your environment.
Use os.walk():
import os
def get_test_wav(folder):
found = []
for root, folders, files in os.walk(folder):
for file in files:
if file == "test.wav":
found.append(os.path.join(root, file))
return found
Or a list comprehension approach:
import os
def get_test_wav(folder):
found = [f"{arr[0]}\\test.wav" for arr in os.walk(folder) if "test.wav" in arr[2]]
return found
I think this might help you How can I search sub-folders using glob.glob module?
The main way to make a list of files in a folder (to make it callable later) is:
file_path = os.path.join(motherdirectopry, 'subdirectory')
list_files = glob.glob(file_path + "/*.wav")
just check that link to see how you can join all sub-directories in a folder.
This will also give you all the file in sub directories that only has .wav at the end:
os.chdir(motherdirectory)
glob.glob('**/*.wav', recursive=True)

How to print the names of files from a folder?

I'm trying to print the names of all the files from a folder directory. I have a folder called "a", and in that folder there are 3 NC files, lets call them "b","c","d", whose directory I want to print. How would I do this?
For example, given my path to the folder is
path=r"C:\\Users\\chz08006\\Documents\\Testing\\a"
I want to print the directories to all the files in the folder "a", so the result should print:
C:\\Users\\chz08006\\Documents\\Testing\\a\\b.nc
C:\\Users\\chz08006\\Documents\\Testing\\a\\c.nc
C:\\Users\\chz08006\\Documents\\Testing\\a\\d.nc
So far, I've tried
for a in path:
print(os.path.basename(path))
But that doesn't seem to be right.
I think you're looking for this:
import os
path = r"C:\\Users\\chz08006\\Documents\\Testing\\a"
for root, dirs, files in os.walk(path):
for file in files:
print("{root}\\{file}".format(root=root, file=file))
You can have a list of file names in a folder using listdir().
import os
path = "C:\\Users\\chz08006\\Documents\\Testing\\a"
l = os.listdir(path)
for a in l:
print(path + a)
You made a couple mistakes. You were using os.path.basename, that only returns the name of the file or folder represented at the end of a path after the last file separator.
Instead, use os.path.abspath to get the full path of any file.
The other mistake was one of using the wrong variable inside the loop (print(os.path.basename(path) instead of using the variable a)
Also, dont forget to use os.listdir to list the files inside the folder before looping.
import os
path = r"C:\Users\chz08006\Documents\Testing\a"
for file in os.listdir(path): #using a better name compared to a
print(os.path.abspath(file)) #you wrote path here, instead of a.
#variable names that do not have a meaning
#make these kinds of errors easier to make,
#and harder to spot

Renaming filenames in python without changing the actual number order?

I have files like:
00001.jpg
00002.jpg
.
.
.
01907.jpg
I want to add some files to this directory which are named the same. But their names should continue like
01908.jpg
01909.jpg
.
.
12906.jpg
I couldn't manage to do that. How can i make this happen?
Thanks a lot:)
I tried
import os
files=[]
files = sorted(os.listdir('directory'))
b=len(files)
for i in range(0,b):
a=files[i]
os.rename(a,(a+1))
print (files)
you have a source dir (which contains the badly/identical named files) and a target dir (which contains files that should not be overwritten).
I would:
list the target dir & sort like you did (the rest of your attempt is clearly off...)
get the last item and parse as integer (without extension): add 1 and that gives the next free index.
loop in the source dir
generate a new name for the current file using the new computed index
use shutil.move or shutil.copy to move/copy the new files with the new name
like this:
import os,shutil
s = "source_directory"
d = "target_directory"
files = sorted(os.listdir(d))
highest_index = int(os.path.splitext(files[-1])[0])+1
for i,f in enumerate(sorted(os.listdir(s)),highest_index):
new_name = "{:05}.png".format(i)
shutil.copy(os.path.join(s,f),os.path.join(d,new_name))
You can do this:
import os
directory1 = 'path to the directory you want to move the files to'
directory2 = 'path to the directory you want to move the files to'
for file in ordered(os.listdir(directory2)):
counter = len(os.listdir(directory1))
file_number = int(file.split('.')[0]) #Get the file number
os.rename(os.path.join(directory2, file), os.path.join(directory1 + str(file_number + counter)))
What I have done:
Looped over the files that I wanted to rename and move.
Found the number of files, which I assumed that it is going to be the same as the name of the last file in this directory, in the main directory which the files are going to be moved to and made sure it will keep updating itself so that no overwrites happen.
Then I got the number of the current file in the loop.
Finally, I used os.rename to rename and move the file from the 1st directory to the 2nd.

Extract a part of a directory in Python 3

I know that similar questions were previously asked but I couldn't find what I need.
For example I have a directory /home/user/dir that contains 5 folders named from 1 to 5.
I need to create a list that will have the following form ['dir/1', 'dir/2','dir/3','dir/4','dir/5'].
I am using Python 3.5 and Ubuntu 14.04.
Thank you for your help!
here is something that can help you.
import glob
dirs = glob.iglob('whatever/the/path/*')
dir_list = ['dir/'+dir for dir in dirs]
In case you have a './' shown before every of you dir, you can easily do
dir_list = ['dir/'+dir[2:] for dir in dirs]
to remove them.

Categories