Save created file into new directory in loop - python

I am currently updating some files I have in a directory, with a loop, and I would like to save those file in a different directory.
Here is what I have:
from astropy.io import fits
from mpdaf.obj import Spectrum, WaveCoord
import os, glob
ROOT_DIR=input("Enter root directory : ")
os.chdir(ROOT_DIR)
destination=input("Enter destination directory : ")
fits_files = glob.glob("*.fits")
for spect in fits_files:
spe = Spectrum(filename= spect, ext=[0,1])
(spect_name, ext) = os.path.splitext(spect)
sperebin = spe.rebin(57)
sperebin.write(spect_name + "-" + "rebin" + ".fits")
With the last line sperebin.write(spect_name + "-" + "rebin" + ".fits") it is currently writing the file in the directory I'm in, and I would like it to write it directly into the destination directory, any idea how to proceed?

With os.path.join you can combine directory with filename to get the file path.
sperebin.write(os.path.join(destination, pect_name + "-" + "rebin" + ".fits"))
Also with os you can check if the directory exists and create it if you want to.
if not os.path.exists(destination):
os.makedirs(destination)

You don't need to or want to change directories in your script. Instead, use pathlib to simplify the creation of the new filename.
from pathlib import Path
root_dir = Path(input("Enter root directory : "))
destination_dir = Path(input("Enter destination directory : "))
# Spectrum wants a string for the filename argument
# so you need to call str on the Path object
for pth in root_dir.glob("*.fits"):
spe = Spectrum(filename=str(pth), ext=[0,1])
sperebin = spe.rebin(57)
dest_pth = destination_dir / pth.stem / "-rebin" / pth.suffix
sperebin.write(str(dest_pth))

Related

Recalling a variable created in an if statement

I am iterating through files in a directory. But I only need files with .csv extension. Then I need to use the path to those files to use them later in the code. Do determine if the file is .csv I use this:
for subdir in os.listdir(root):
for file in os.listdir(os.path.join(root,subdir)):
if file.endswith(ext):
print(file)
This gives me all the files with .csv extension. Now I want to create a string with the path to these files so I use this:
for subdir in os.listdir(root):
for file in os.listdir(os.path.join(root,subdir)):
if file.endswith(ext):
datoteka = root + '\\' + subdir + '\\' + file
The path to my files is now stored in string datoteka and I want to use this inside this for loop. The one that also contains the if statement.
But I get an error that datoteka is not defined. After a quick research I found out that I can not use variables that were defined inside an If statement outside of that If statement. Is there a way to pull the variable out?
I need to preform some data analysis on the files (datoteka contains the path.):
for subdir in os.listdir(root):
for file in os.listdir(os.path.join(root,subdir)):
if file.endswith(ext):
datoteka = root + '\\' + subdir + '\\' + file
df = pd.read_csv(datoteka, encoding = 'cp1252')
This gives the following error:
Is there another way I could get my paths without defining datoteka inside that If statemnet?
Use glob and build a list of files like this:
from os.path import join
from glob import glob
from pandas import read_csv
ROOT = 'root' # root directory
SUBDIR = 'sub' # sub directory
list_of_csvs = [file for file in glob(join(ROOT, SUBDIR, '*.csv'))]
# now iterate over the list
for file in list_of_csvs:
df = read_csv(file)
Or, if you don't need to keep the list of files and want a recursive search then it's just:
from os.path import join
from glob import glob
from pandas import read_csv
ROOT = 'root' # root directory
for file in glob(join(ROOT, '**', '*.csv'), recursive=True):
df = read_csv(file)
The variable "datoteka" is defined inside the if block so this can't be accessed outside the block, so define the variable outside the for loop.
Example :
for subdir in os.listdir(root):
datoteka = None
for file in os.listdir(os.path.join(root,subdir)):
if file.endswith(ext):
datoteka = root + '\\' + subdir + '\\' + file
if datoteka is not None:
df = pd.read_csv(datoteka, encoding = 'cp1252')

Python: copying files group to subdirectories

I'm working with Python and I'd like to copy 3 files of a certain folder
/Users/jake/Desktop/exp to all the subfolders of other sub-directories belonging to the directory /toyspace:
/Users/jake/Desktop/toyspace/1A/AAA
/Users/jake/Desktop/toyspace/1A/BBB
/Users/jake/Desktop/toyspace/1A/CCC
/Users/jake/Desktop/toyspace/2B/AAA
/Users/jake/Desktop/toyspace/2B/BBB
/Users/jake/Desktop/toyspace/2B/CCC
So the subfolders names are the same for all the sub-directories. I wrote something like that:
from distutils.dir_util import copy_tree
def myfunc (source, destination):
fromDirectory = source
toDirectory = destination
copy_tree(fromDirectory, toDirectory)
for subfold in toDirectory:
myfunc(fromDirectory, subfold)
Where source =/Users/jake/Desktop/exp and destination =/Users/jake/Desktop/toyspace, but it returns me an error:
DistutilsFileError: could not create '/motif_list.txt': Read-only file system
Can you help me? Thanks in advance!
Unfortunately I have not used distutils but you can try to automate using the os command as below
import os
def copy_folders(source_dir, destination_dir):
files = os.listdir(source_dir)
for sub_folder1 in os.listdir(destination_dir):
for sub_folder in os.listdir(destination_dir + sub_folder1 + '/'):
for file in files:
os.system('cp ' + source_dir + file + ' ' + destination_dir + sub_folder1 + '/' + sub_folder + '/')
Let me know how it goes :)

removing substrings from subdirectory names using values held in list

I have a parent directory that contains a lot of subdirectories. I want to create a script that loops through all of the subdirectories and removes any key words that I have specified in the list variable.
I am not entirely sure how to acheive this.
Currently I have this:
import os
directory = next(os.walk('.'))[1]
stringstoremove = ['string1','string2','string3','string4','string5']
for folders in directory:
os.rename
And maybe this type of logic to check to see if the string exists within the subdirectory name:
if any(words in inputstring for words in stringstoremove):
print ("TRUE")
else:
print ("FALSE")
Trying my best to to deconstruct the task, but I'm going round in circles now
Thanks guys
Startng from your existing code:
import os
directory = next(os.walk('.'))[1]
stringstoremove = ['string1','string2','string3','string4','string5']
for folder in directory :
new_folder = folder
for r in stringstoremove :
new_folder = new_folder.replace( r, '')
if folder != new_folder : # don't rename if it's the same
os.rename( folder, new_folder )
If you want to rename those sub directories which match in your stringstoremove list then following script will be helpful.
import os
import re
path = "./" # parent directory path
sub_dirs = os.listdir(path)
stringstoremove = ['string1','string2','string3','string4','string5']
for directory_name in sub_dirs:
if os.path.isdir(path + directory):
for string in stringstoremove:
if string in directory_name:
try:
new_name = re.sub(string, "", directory_name)
os.rename(path + directory, path + new_name) # rename this directory
except Exception as e:
print (e)

How to use the current folder the program is in?

When I open a file, I have to specify the directory that it is in. Is there a way to specify using the current directory instead of writing out the path name? I'm using:
source = os.listdir("../mydirectory")
But the program will only work if it is placed in a directory called "mydirectory". I want the program to work in the directory it is in, no matter what the name is.
def copyfiles(servername):
source = os.listdir("../mydirectory") # directory where original configs are located
destination = '//' + servername + r'/c$/remotedir/' # destination server directory
for files in source:
if files.endswith("myfile.config"):
try:
os.makedirs(destination, exist_ok=True)
shutil.copy(files,destination)
except:
this is a pathlib version:
from pathlib import Path
HERE = Path(__file__).parent
source = list((HERE / "../mydirectory").iterdir())
if you prefer os.path:
import os.path
HERE = os.path.dirname(__file__)
source = os.listdir(os.path.join(HERE, "../mydirectory"))
note: this will often be different from the current working directory
os.getcwd() # or '.'
__file__ is the filename of your current python file. HERE is now the path of the directory where your python file lives.
'.' stands for the current directory.
try:
os.listdir('./')
or:
os.listdir(os.getcwd())

How to rename a file using Python

I want to change a.txt to b.kml.
Use os.rename:
import os
os.rename('a.txt', 'b.kml')
Usage:
os.rename('from.extension.whatever','to.another.extension')
File may be inside a directory, in that case specify the path:
import os
old_file = os.path.join("directory", "a.txt")
new_file = os.path.join("directory", "b.kml")
os.rename(old_file, new_file)
As of Python 3.4 one can use the pathlib module to solve this.
If you happen to be on an older version, you can use the backported version found here
Let's assume you are not in the root path (just to add a bit of difficulty to it) you want to rename, and have to provide a full path, we can look at this:
some_path = 'a/b/c/the_file.extension'
So, you can take your path and create a Path object out of it:
from pathlib import Path
p = Path(some_path)
Just to provide some information around this object we have now, we can extract things out of it. For example, if for whatever reason we want to rename the file by modifying the filename from the_file to the_file_1, then we can get the filename part:
name_without_extension = p.stem
And still hold the extension in hand as well:
ext = p.suffix
We can perform our modification with a simple string manipulation:
Python 3.6 and greater make use of f-strings!
new_file_name = f"{name_without_extension}_1"
Otherwise:
new_file_name = "{}_{}".format(name_without_extension, 1)
And now we can perform our rename by calling the rename method on the path object we created and appending the ext to complete the proper rename structure we want:
p.rename(Path(p.parent, new_file_name + ext))
More shortly to showcase its simplicity:
Python 3.6+:
from pathlib import Path
p = Path(some_path)
p.rename(Path(p.parent, f"{p.stem}_1_{p.suffix}"))
Versions less than Python 3.6 use the string format method instead:
from pathlib import Path
p = Path(some_path)
p.rename(Path(p.parent, "{}_{}_{}".format(p.stem, 1, p.suffix))
import shutil
shutil.move('a.txt', 'b.kml')
This will work to rename or move a file.
os.rename(old, new)
This is found in the Python docs: http://docs.python.org/library/os.html
As of Python version 3.3 and later, it is generally preferred to use os.replace instead of os.rename so FileExistsError is not raised if the destination file already exists.
assert os.path.isfile('old.txt')
assert os.path.isfile('new.txt')
os.rename('old.txt', 'new.txt')
# Raises FileExistsError
os.replace('old.txt', 'new.txt')
# Does not raise exception
assert not os.path.isfile('old.txt')
assert os.path.isfile('new.txt')
See the documentation.
Use os.rename. But you have to pass full path of both files to the function. If I have a file a.txt on my desktop so I will do and also I have to give full of renamed file too.
os.rename('C:\\Users\\Desktop\\a.txt', 'C:\\Users\\Desktop\\b.kml')
One important point to note here, we should check if any files exists with the new filename.
suppose if b.kml file exists then renaming other file with the same filename leads to deletion of existing b.kml.
import os
if not os.path.exists('b.kml'):
os.rename('a.txt','b.kml')
import os
# Set the path
path = 'a\\b\\c'
# save current working directory
saved_cwd = os.getcwd()
# change your cwd to the directory which contains files
os.chdir(path)
os.rename('a.txt', 'b.klm')
# moving back to the directory you were in
os.chdir(saved_cwd)
Using the Pathlib library's Path.rename instead of os.rename:
import pathlib
original_path = pathlib.Path('a.txt')
new_path = original_path.rename('b.kml')
Here is an example using pathlib only without touching os which changes the names of all files in a directory, based on a string replace operation without using also string concatenation:
from pathlib import Path
path = Path('/talend/studio/plugins/org.talend.designer.components.bigdata_7.3.1.20200214_1052\components/tMongoDB44Connection')
for p in path.glob("tMongoDBConnection*"):
new_name = p.name.replace("tMongoDBConnection", "tMongoDB44Connection")
new_name = p.parent/new_name
p.rename(new_name)
import shutil
import os
files = os.listdir("./pics/")
for key in range(0, len(files)):
print files[key]
shutil.move("./pics/" + files[key],"./pics/img" + str(key) + ".jpeg")
This should do it. python 3+
How to change the first letter of filename in a directory:
import os
path = "/"
for file in os.listdir(path):
os.rename(path + file, path + file.lower().capitalize())
then = os.listdir(path)
print(then)
If you are Using Windows and you want to rename your 1000s of files in a folder then:
You can use the below code. (Python3)
import os
path = os.chdir(input("Enter the path of the Your Image Folder : ")) #Here put the path of your folder where your images are stored
image_name = input("Enter your Image name : ") #Here, enter the name you want your images to have
i = 0
for file in os.listdir(path):
new_file_name = image_name+"_" + str(i) + ".jpg" #here you can change the extention of your renmamed file.
os.rename(file,new_file_name)
i = i + 1
input("Renamed all Images!!")
os.chdir(r"D:\Folder1\Folder2")
os.rename(src,dst)
#src and dst should be inside Folder2
import os
import re
from pathlib import Path
for f in os.listdir(training_data_dir2):
for file in os.listdir( training_data_dir2 + '/' + f):
oldfile= Path(training_data_dir2 + '/' + f + '/' + file)
newfile = Path(training_data_dir2 + '/' + f + '/' + file[49:])
p=oldfile
p.rename(newfile)
You can use os.system to invoke terminal to accomplish the task:
os.system('mv oldfile newfile')

Categories

Resources