copy and rename files in a directory in a specific pattern - python

I would like to copy a file lying in a directory equal to the number of times the other files lying in that directory and then rename all the new files.
For example, there are 3 files in a directory, filename1.xls, filename2.xls and filename3.xls. I would like to copy Filename1.xls 2 times (as there are 2 files in the directory excluding filename1.xls )and then rename each copied file as filename2.xls and fiilename3.xls. Hope my question is clear. Thanks, AD

hm... just get the amount of files in directory, copy your file N times and save them as
for number in range(amount):
"feliname%r.xls" % number
if I understand what you mean

To replace content of all files that have names that start with "F" and that are adjacent to a file given at the command-line with its copy:
#!/usr/bin/env python
import os
import shutil
import sys
filename = sys.argv[1] # provide file you want to multiply
dirname, basename = os.path.split(filename)
for name in os.listdir(dirname):
path = os.path.join(dirname, name)
#note: os.path.normcase() might be required to compare names
if name.startswith("F") and name != basename and os.path.isfile(path):
shutil.copy2(filename, path) #note: some metadata is not copied
Note: if the copy fails; the destination file might be destroyed. You can copy to a temporary file first in this case before replacing the destination.

Related

Moving Files from directory to their own folders

I am struggling with the paths and directories to solve this problem. Basically, I have a long list of .lammps files in one directory. My goal is to copy each file and move it into its own folder (which is one directory back) where its folder name is the file name minus the .lammps. All of the folders are already made, I just can't seem to figure out moving them. The entire list of files is in the Files directory. The individual folders are in the ROTATED FILES directory. Here is what I have. Any tips greatly appreciated.
Here is a file example
n-optimized.new.10_10-90-10_10.Ni00Nj01.lammps
The folder for this file is then named
n-optimized.new.10_10-90-10_10.Ni00Nj01
import os
file_directory = os.chdir("C:\Py Practice\ROTATED FILES\Files")
files = os.listdir()
for file in files:
# get the file -.lammps string
name1 = file.split('.')[0:4]
name2 = ".".join(name1)
# get the path for the files new respective folder (back a directory and paste folder name)
file_folder = "C:\Py Practice\ROTATED FILES/" + name2
# Move
combined_path = os.path.join(file, file_folder)
I've tried shutil and figured path join might be easier.
First of all, the code you have here shouldn't work since you either have to escape backslashes or use a raw string. Secondly, rather than using os for file system operations, it's much better to learn how to use pathlib (also a core python module) which provides a more modern object-oriented approach to file operations.
Using pathlib and shutil you can do something like
from pathlib import Path
from shutil import copyfile
file_directory = Path(r"C:\Py Practice\ROTATED FILES\Files")
# get the list of source files
source_files = [f for f in file_directory.glob('*.lammps')]
# create target file paths
target_files = [file_directory.parent / f.stem/ f.name for f in source_files]
for source, target in zip(source_files, target_files):
copyfile(str(source), str(target))
Here we're accessing different parts of file path using a convenient OOP structure. For example, if your file f is located in 'c:/foo/bar/boo.txt' then f.name is just the name of file: boo.txt, f.stem is the stem part of the file name (excluding the extension) boo, f.parent is its parent directory 'c:/foo/bar/' etc.
There's a really handy graphic of pathlib Path objects here.
The only inconvenience is that not all of core modules support Path objects yet so for copyfile we just need to get the string representation by calling str on the object.
And you don't even need to have target folders created beforehand, it's very easy to create the necessary folder structure as you go along:
from pathlib import Path
from shutil import copyfile
file_directory = Path(r"C:\Py Practice\ROTATED FILES\Files")
# get the list of source files
source_files = [f for f in file_directory.glob('*.lammps')]
# create target file paths
target_files = [file_directory.parent / f.stem/ f.name for f in source_files]
for source, target in zip(source_files, target_files):
# check that target directory exists
# and create a folder if not
if not target.parent.is_dir():
target.parent.mkdir()
copyfile(str(source), str(target))

loop over subfolder inside a folder in python

I am trying to move files from one folder to another. I have a folder name from a to z. Inside each folder(a-z) i have several folders. I can move files from the subfolder of the folder(a-z) to my folder but I want to do it from a-z at once.
folder structure : a--ab
--ac
b--bc
--bd
.. till z
import glob
import os
import shutil
path = "E:\\download\\images\\a\\*"
move_path = "E:\\download\\images\\final\\"
files = glob.glob(path,recursive = True)
for file in files:
subfile= os.listdir(file)
for sub in subfile:
subpath = file + "\\" + sub
shutil.move(subpath,move_path +"\\" + sub)
Copy this tiny script in E:\download\images and run it from there. This way, the Path class will use that directory as the working root directory.
The images variable will contain a generator that will give you every file matching the glob (which means: every file in every subfolder that has a 3-letter extension and with the first subfolder's name having only one character).
When renaming, the file will be moved from the subfolder path to final/, thus being moved.
Keep in mind that the glob will pick every file or folder name having a 3-letter extension. You'll need to do additional checks if you have other files or folders that match this nomenclature.
from pathlib import Path
images = Path().glob('?/**/*.???')
for img in images:
img.rename('final/' + img.name)

Search a folder and sub folders for files starting with criteria

I have a folder "c:\test" , the folder "test" contains many sub folders and files (.xml, .wav). I need to search all folders for files in the test folder and all sub-folders, starting with the number 4 and being 7 characters long in it and copy these files to another folder called 'c:\test.copy' using python. any other files need to be ignored.
So far i can copy the files starting with a 4 but not structure to the new folder using the following,
from glob import glob
import os, shutil
root_src_dir = r'C:/test' #Path of the source directory
root_dst_dir = 'c:/test.copy' #Path to the destination directory
for file in glob('c:/test/**/4*.*'):
shutil.copy(file, root_dst_dir)
any help would be most welcome
You can use os.walk:
import os
import shutil
root_src_dir = r'C:/test' #Path of the source directory
root_dst_dir = 'c:/test.copy' #Path to the destination directory
for root, _, files in os.walk(root_src_dir):
for file in files:
if file.startswith("4") and len(file) == 7:
shutil.copy(os.path.join(root, file), root_dst_dir)
If, by 7 characters, you mean 7 characters without the file extension, then replace len(file) == 7 with len(os.path.splitext(file)[0]) == 7.
This can be done using the os and shutil modules:
import os
import shutil
Firstly, we need to establish the source and destination paths. source should the be the directory you are copying and destination should be the directory you want to copy into.
source = r"/root/path/to/source"
destination = r"/root/path/to/destination"
Next, we have to check if the destination path exists because shutil.copytree() will raise a FileExistsError if the destination path already exists. If it does already exist, we can remove the tree and duplicate it again. You can think of this block of code as simply refreshing the duplicate directory:
if os.path.exists(destination):
shutil.rmtree(destination)
shutil.copytree(source, destination)
Then, we can use os.walk to recursively navigate the entire directory, including subdirectories:
for path, _, files in os.walk(destination):
for file in files:
if not file.startswith("4") and len(os.path.splitext(file)[0]) != 7:
os.remove(os.path.join(path, file))
if not os.listdir(path):
os.rmdir(path)
We then can loop through the files in each directory and check if the file does not meet your condition (starts with "4" and has a length of 7). If it does not meet the condition, we simply remove it from the directory using os.remove.
The final if-statement checks if the directory is now empty. If the directory is empty after removing the files, we simply delete that directory using os.rmdir.

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.

Python code to find all newly created, modified and deleted files in all the directories/sub-directories starting from / directory

I know how to list all subdirectories and files in a directory tree. But I am looking for way to list all newly created files, modified and (if possible) deleted files in all the directories in a directory tree starting from the root directory.
You could find all files created or modified in the last half-hour by looking at the "mtime" of each file:
import os
import datetime as dt
now = dt.datetime.now()
ago = now-dt.timedelta(minutes=30)
for root, dirs,files in os.walk('.'):
for fname in files:
path = os.path.join(root, fname)
st = os.stat(path)
mtime = dt.datetime.fromtimestamp(st.st_mtime)
if mtime > ago:
print('%s modified %s'%(path, mtime))
To generate a list of deleted files, you'd also have to have a list of files 30 minutes ago.
A more robust alternative is to use a revision control system like git. Making a commit of all the files in the directory is like making a snapshot. Then the command
git status -s
would list all files that have changed since the last commit. This will list files that have been deleted too.
from tempfile import mkstemp
import shutil
import os
import datetime as dt
import sys
# gets the time frame we are going to look back and builds a placeholder list to passover the info from our mtime to slay
now=dt.datetime.now()
ago=now-dt.timedelta(minutes=480)
passover=[]
# the '.' is the directory we want to look in leave it to '.' if you want to search the directory the file currently resides in
for root,dirs,files in os.walk('.'):
for fname in files:
path=os.path.join(root,fname)
st=os.stat(path)
mtime=dt.datetime.fromtimestamp(st.st_mtime)
if mtime>ago:
passover.append(path)
def slay(file_path, pattern, subst):
#Create temp file
fh, abs_path = mkstemp()
with open(abs_path,'w') as new_file:
with open(file_path) as old_file:
for line in old_file:
new_file.write(line.replace(pattern, subst))
old_file.close()
#Remove original file
os.remove(file_path)
#Move new file
try:
shutil.move(abs_path, file_path)
except WindowsError:
pass
#we pass the passover list to the slay command in a for loop in order to do muiltple replaces in those files.
for i in passover:
slay(i,"String1","String2")
Take a look at "man find"
create a temp file to compare
example:
find / -type f -newerB tempFile
some part of the man find
-newerXY reference
Compares the timestamp of the current file with reference. The reference argument is normally the name of a file (and one
of its timestamps is used for the comparison) but it may also be a string describing an absolute time. X and Y are placeā€
holders for other letters, and these letters select which time belonging to how reference is used for the comparison.
a The access time of the file reference
B The birth time of the file reference
c The inode status change time of reference
m The modification time of the file reference
t reference is interpreted directly as a time

Categories