Iterating files in directory by name - python

Ok, I have a directory with many files and subdirectories; among these ones there are 20 directories called mbr001, mbr002, ... until mbr020 that are the ones I am interested in.
I want to write a program that iteratively goes into mbr001, do somethings, then to mbr002, do the same things, and so on.
A solution with Python's os.chdir('./mbr001') until 20 seems pretty inefficient.
Besides, when I am in such directories, let's say for example mbr012, I want to create a variable that has in its name the number of the mbr where I am, in this case 12. Something like variable = 'mbr012_file.dat'. (This variable is used in what I am doing inside each directory, not relevant here).
What I would need would be something like this (note this is pseudo-code):
for i in mbr[i]:
variable = "mbr[i]_file.dat"
...
How can I do the loop and the variable naming? Thanks in advance.

What about something like this ?
for i in range(1, 21):
dn = "./mbr{:03}".format(i)
var = "mbr{:03}_file.dat".format(i)
os.chdir(dn)
# Do your stuff here
#
#
os.chdir("..")

Use format:
for i in list_of_is:
filename = "mbr{0:02d}_file.dat".format(i)

You just need to concatenate '_files.dat' into the directory name
import re
for i in mbr_list:
variable = i + '_files.dat'
# use regex if you only interest on the numeric part
# variable = re.sub('mbr(\d+)', r'mbr\1_file.dat', i)
# do your thing here

In python 3.4 and above you can use pathlib and in python 3.6 and above you can use "f string" to format text
from pathlib import Path
for path in [d for d in Path.cwd().iterdir() if d.match("mbr*")]:
variable = f"{path.name}_file.dat"
# do other stuff

Related

How to correctly apply a RE for obtaining the last name (of a file or folder) from a given path and print it on Python?

I have wrote a code which creates a dictionary that stores all the absolute paths of folders from the current path as keys, and all of its filenames as values, respectively. This code would only be applied to paths that have folders which only contain file images. Here:
import os
import re
# Main method
the_dictionary_list = {}
for name in os.listdir("."):
if os.path.isdir(name):
path = os.path.abspath(name)
print(f'\u001b[45m{path}\033[0m')
match = re.match(r'/(?:[^\\])[^\\]*$', path)
print(match)
list_of_file_contents = os.listdir(path)
print(f'\033[46m{list_of_file_contents}')
the_dictionary_list[path] = list_of_file_contents
print('\n')
print('\u001b[43mthe_dictionary_list:\033[0m')
print(the_dictionary_list)
The thing is, that I want this dictionary to store only the last folder names as keys instead of its absolute paths, so I was planning to use this re /(?:[^\\])[^\\]*$, which would be responsible for obtaining the last name (of a file or folder from a given path), and then add those last names as keys in the dictionary in the for loop.
I wanted to test the code above first to see if it was doing what I wanted, but it didn't seem so, the value of the match variable became None in each iteration, which didn't make sense to me, everything else works fine.
So I would like to know what I'm doing wrong here.
I would highly recommend to use the builtin library pathlib. It would appear you are interested in the f.name part. Here is a cheat sheet.
I decided to rewrite the code above, in case of wanting to apply it only in the current directory (where this program would be found).
import os
# Main method
the_dictionary_list = {}
for subdir in os.listdir("."):
if os.path.isdir(subdir):
path = os.path.abspath(subdir)
print(f'\u001b[45m{path}\033[0m')
list_of_file_contents = os.listdir(path)
print(f'\033[46m{list_of_file_contents}')
the_dictionary_list[subdir] = list_of_file_contents
print('\n')
print('\033[1;37;40mThe dictionary list:\033[0m')
for subdir in the_dictionary_list:
print('\u001b[43m'+subdir+'\033[0m')
for archivo in the_dictionary_list[subdir]:
print(" ", archivo)
print('\n')
print(the_dictionary_list)
This would be useful in case the user wants to run the program with a double click on a specific location (my personal case)

How to make subfolders inside a parameterized folder?

I made a folder and inside there are 100 subfolders which are made by parameters. Now I want to create one subfolder inside each of this 100 subfolders. But whatever I am doing it is not working.
I added a simple example.
number=[1,2,3]
for i in range (len(number)):
Name = 'GD_%d'%(number[i])
os.mkdir('C:/Temp/t2_t1_18/'+Name) #till this works fine
subfolder_name='S1_%d'%(number[i])
#This does not work and idea somehow not correct
os.mkdir(os.path.join('C:/Temp/t2_t1_18/Name'+subfolder_name))
Some Notes
It is better not to use string concatenation when concatenating paths.
Since you just need the numbers it is better to iterate over them, instead of using range
You can take a look at python's new way of formatting https://realpython.com/python-f-strings/
Assuming I got your question right and you want to create a subdirectory in the newly created directory, I would do something like that
import os
numbers = [1,2,3]
main_dir = os.path.normpath('C:/Temp/t2_t1_18/')
for number in numbers:
dir_name = f'GD_{number}'
# dir_name = 'GD_{}'.format(number) # python < 3.6
dir_path = os.path.join(main_dir, dir_name)
os.mkdir(dir_path)
subdir_name = f'S1_{number}'
subdir_path = os.path.join(dir_path, subdir_name)
os.mkdir(subdir_path)
There is a better answer to your question already.
In your example this should be an easy solution (if your Python version is sufficient):
from pathlib import Path
numbers = (1, 2, 3, 4)
for n in numbers:
Path(f"C:/Temp/t2_t1_18/GD_{n}/S1_{n}").mkdir(parents=True, exist_ok=True)
I'm not certain I understand what you're trying to do, but here is a version of your code that is cleaned up a bit. It assumes the C:\Temp directory exists, and will create 3 folders in C:\Temp, and 1 subfolder in each of those 3 folders.
import os
numbers = [1,2,3]
base_path = os.path.join('C:/', 'Temp')
for number in numbers:
# create the directory C:\Temp\{name}
os.mkdir(os.path.join(base_path, f'GD_{number}'))
# create the directory C:\Temp\{name}\{subfolder_name}
os.mkdir(os.path.join(base_path, f'GD_{number}', f'S1_{number}'))
Some Notes and Tips:
Indentation is part of the syntax in python, so make sure you indent every line that is in a code block (such as your for loop)
There are many ways to format strings, I like f-strings (a.k.a. string interpolation) which were introduced in python 3.6. If you're using an earlier version of python, either update, or use a different string formatting method. Whatever you choose, be consistent.
It is a good idea to use os.path.join() when working with paths, as you were trying to do. I expanded the use of this method in the code above.
As another answer pointed out, you can simply iterate over your numbers collection instead of using range() and indexing.

How to modify a path which's in a variable (python)?

After finding the path of the Python file which I am actually working on with os.getcwd() and __file__ I want to modify it, so if I put it in a variable named r and then delete one part of the path that will be very good. For example, the path is 'C:\\Users\\Shadow\\Desktop\\213.py' if I want to delete \\213.py from the path (r) how can I do that?
you can manipulate your string:
r = 'C:\\Users\\Shadow\\Desktop\\213.py'
r.rsplit('\\', 1)[0]
output:
'C:\\Users\\Shadow\\Desktop'
you may also want to have a look over pathlib.Path
You extract the directory name in your example. This is easily achieved with os.path.dirname.
import os
os.path.dirname(__file__)
This solution is cross-platform (mostly), and avoids most pitfalls that arise from treating paths as strings.
If you need the value stored in a variable:
import os
r = on.path.dirname(__file__)

Using input to change directory path

I'm kinda new to python and I feel like the answer to this is so simple but I have no idea what the answer is. I'm trying to move files from one place to another but I don't want to have to change my code every time I wanna move that file so I just want to get user input from the terminal.
import shutil
loop = True
while loop:
a = input()
shutil.move("/home/Path/a", "/home/Path/Pictures")
What do I have to put around the a so that it doesn't read it as part of the string?
This should do what you want. the os.path.join() will combine the string value in a, that you get from input with the first part of the path you have provided. You should use os.path.join() as this will form paths in a way that is system independent.
import shutil
import os
loop = True
while loop:
a = input()
shutil.move(os.path.join("/home/Path/", a), "/home/Path/Pictures")
Output:
>>> a = input()
test.txt
>>> path = os.path.join("/home/Path/", a)
>>> path
'/home/Path/test.txt'
You can also use "/home/Path/{0}".format(a) which will swap the value of a with {0}, or you can do do "/home/Path/{0}" + str(a) which will also do what you want.
Edited to account for Question in comment:
This will work if your directory doesn't have any sub-directories. it may still work if there are directories and files in there but I didn't test that.
import shutil
import os
files = os.listdir("/home/Path/")
for file in files:
shutil.move(os.path.join("/home/Path/", file), "/home/Path/Pictures")
one solution
a = 'test.csv'
path = '/home/Path/{}'.format(a)
>>> path
/home/Path/test.csv

Creating path-names with variables in Python 2.7

I'd like to create some folders to store results of some simulations in a logical way with a naming system.
My code has 4 main parameters that I'm investigating and I'd like to dynamically create paths with these parameters in the pathnames, example below:
a = 'test'
b = 2
c = 3
d = 4
os.chdir('./results/test_b_c_d/outputs')
I'll manually change the values of a-d for now as these are just a few test results. A needs to be a string but b-d are just integers.
I've seen I can do
os.path.join('./results/', test, '/outputs/'))
Where the 'join' command will add a folder of that name in that path directory, but can I use this or a similar command to change the actual folder name with changing variables?
Thanks
You're looking for str.format:
>>> print("./results/{a}_{b}_{c}_{d}/outputs".format(a=a, b=b, c=c, d=d))
./results/test_2_3_4/outputs
To create a string including variables values (well, the string representation of variables values), you want str.format():
a = 'test'
b = 2
c = 3
d = 4
dirname = "{}_{}_{}_{}".format(a, b, c d)
Then you use os.path.join() to create the full path in a portable way (so your code works on any supported OS). Also it's better to use absolute path (this make the code more predictable) instead of relying on either os-specific stuff ("./xxx") and/or os.chdir(). Here I'm using o.getcwd() to use the current working directory as root but it's better to use something more reliable, based either on the current user's homedir, the application's directory or some command line arg or environment variable:
root = os.getcwd() # or whatever root folder you want
dirpath = os.path.join(root, "results", dirname, "outputs")
And finally, you use os.makedirs to create the whole directory tree in one single call:
if not os.path.exists(dirpath):
os.makedirs(dirpath)
NB :
I've seen I can do os.path.join('./results/', test, '/outputs/')
The point of os.path.join() is to use the appropriate path separators for the current OS, so do not hardcode path separators in your arguments - this should have been os.path.join('results', test, 'outputs')
You can use a mix between str.format to build a string using variables values and os.path.join to build intelligently a path with the right separator (depending on platform).
Example:
a = 'test'
b = 2
c = 3
d = 4
my_path = os.path.join(os.getcwd(), 'results', '{}_{}_{}_{}'.format(a,b,c,d), 'outputs')
os.chdir(my_path)
Not that os.getcwd is one solution to get the current working directory

Categories

Resources