Replace folders and files with the most recent ones - python

I want to copy folders and files from a source directory to another destination directory. Each directory contains subfolders and many files already.
So far, I try the following code, inspired by a post in Stackoverflow:
import os
import shutil
root_src_dir = r'C:\....'
root_dst_dir = r'C:\....'
for src_dir, dirs, files in os.walk(root_src_dir):
dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1)
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
for file_ in files:
src_file = os.path.join(src_dir, file_)
dst_file = os.path.join(dst_dir, file_)
if os.path.exists(dst_file):
# in case of the src and dst are the same file
if os.path.samefile(src_file, dst_file):
continue
os.remove(dst_file)
shutil.copy2(src_file, dst_dir)
This code equates destination directory with source directory for identical folder and file names. This can replace the most recent folders and files in the destination, which is a disaster, while I want to keep the newest ones stay in both directories, when they had identical folder and file names.

This is a program i wrote. It is a interactive one also with move and delete function along with copy. And filters data based on the extension.
import os
import shutil
from os.path import join
from time import perf_counter
print('Written By : SaGaR')
print('Applies operation on all the files with specified ext. to the destination path specified:')
scandir=input('Enter the path to scan(absolute or relative path):')
print(f'You entered :{scandir}')
choice = input('Enter operation to perform(move|copy|delete|list):').lower()
EXCLUDE=['Android','DCIM', 'documents', 'WhatsApp', 'MIUI','bluetooth'] #exclude some system folder on android . Add your one also.
if choice == 'copy' or choice =='move':
dest=input('Enter the destination path(absolute or relative path):')
print(f'You entered :{dest}')
EXCLUDE.append(dest)
DATA_TYPES=input('Enter Data types to filter(comma-seprated)(ex.- jpg,txt): ').split(',')
files2=[]
print('*'*5,'FINDING FILES')
for root, dirs, files in os.walk(scandir):
for file in files:
for typ in DATA_TYPES:
if file.endswith(typ):
a = join(root,file)
print(root, end='')
print('-->',file)
files2.append(a)
for directory in EXCLUDE:
if directory in dirs:
dirs.remove(directory)
def copy_move_files():
start=perf_counter()
print('-'*5, f'Trying To {choice.capitalize} Files')
if not os.path.isdir(dest):
print(f'{dest} does not exists')
print(f'Creating {dest} directory')
os.mkdir(dest)
else:
print(f'{dest} exists')
for file in files2:
fpath=os.path.join(dest,os.path.split(file)[-1])
try:
if not os.path.exists(fpath):
if choice=='move':
shutil.move(file,dest)
print(f'{file.split("/")[-1]} Moved Successfully')
if choice=='copy':
shutil.copy(file,dest)
print(f'{file.split("/")[-1]} Copied Successfully')
else:
print(f'{file.split("/")[-1]} Already in destination folder')
except shutil.SameFileError:
print(f'{file.split("/")[-1].strip()} Already Exists in the destination directory. Add the Destination directory to EXCLUDE ')
end = perf_counter() - start
print(f'Operation took {end} second(s)')
def delete_files():
print('-'*5, 'Trying To Delete Files')
for file in files2:
os.remove(file)
print(f'{file} deleted')
if choice == 'copy' or choice=='move':
copy_move_files()
elif choice == 'delete':
delete_files()
else:
print('No valid or "list" option detected\nOnly listing Files')
print('Exiting the program Now')

This is a solution using shutil.copytree and a my_copy function.
In my_copy there is an if statement that check which is the newest file.
import os
import shutil
def my_copy(src, dst):
print(src)
print(dst)
if not os.path.exists(dst):
shutil.copy2(src,dst)
else:
if os.path.getmtime(src) > os.path.getmtime(dst):
shutil.copy2(src,dst)
return True
def rec_copy():
root_src_dir = r'C:\...'
root_dst_dir = r'C:\...'
try:
if not os.path.exists(root_dst_dir):
print(os.path.exists(root_dst_dir))
os.makedirs(root_dst_dir)
print(os.path.exists(root_dst_dir))
shutil.copytree(root_src_dir , root_dst_dir, copy_function=my_copy, dirs_exist_ok=True)
except Exception as err:
print(err)

Related

Python Selective Copy Homework Assistance

Selective Copy:
Write a program that walks through a folder tree and searches for
files with a certain file extension (such as .pdf or .jpg). Copy these
files from whatever location they are into a new folder.
I keep getting a traceback error as seen in this screenshot.
I do not know what I am doing wrong.
This is the code I have:
import os, shutil, sys
def selective_copy(src_folder: str = None, ext: str = None, dest_folder: str = None) -> None:
if src_folder is None:
raise AttributeError('src_folder must be given.')
if ext is None:
raise AttributeError('.jpg')
if dest_folder is None:
raise AttributeError('dest_folder must be given.')
src_folder = os.path.abspath(src_folder)
os.chdir(src_folder)
os.mkdir(dest_folder)
# Walk through a folder tree
for foldername, subfolders, filenames in os.walk("./"):
print("Looking in folder: %s..." % foldername)
# Find files with a specific extension
for filename in filenames:
if filename.endswith('.jpg'):
# Copy files to a new folder
print("Copying file: %s..." % filename)
shutil.copy(filename, dest_folder)
print("Done.")
def main():
selective_copy('../', '.jpg', 'new_folder')
if __name__ == '__main__':
main()
Instead of os.mkdir(), I would suggest looking at os.makedirs() (documentation). It has a parameter that I believe you'll find useful for this situation.

Moving files with python using a list .txt

I want to move files from one directory to another from a .txt file containing the names of the files to be moved, the script must first browse the directory and if it finds the file it moves it to the new directory. Where to start? I've managed to do this for a file list but I'd like to do it directly via the .txt file without rewriting the names of the files to be moved
import shutil, os
files = ['file1.txt', 'file2.txt', 'file3.txt', 'file4.txt']
for file in files:
shutil.move(file, 'destination_directory')
As I know, U cant move your files with .txt
Just move your file_path
You can use my code below.
I have double checked and it work on my side.
Sorry for my poor English Skill :)
import os
import shutil
from pathlib import Path
def create_directory(dir_name: str):
"""To create directory before create files: txt, csv..."""
system_path = os.getcwd()
dir_path = os.path.join(system_path, dir_name)
try:
os.makedirs(dir_path, exist_ok=True)
except OSError as error:
print("Directory '%s' can not be created" % dir_name)
return dir_path
def create_files(dir_path: str, file_name: str):
"""Function for creating files"""
file_path = dir_path + fr"\{file_name}"
with open(file_path, "w") as open_file:
if Path(file_path).is_file():
print(f'File: {file_name} created successfully')
else:
print(f'File: {file_name} does not exist')
open_file.close() # Need to close.
return file_path
def main():
# Step 1: Creating file1.txt, file2.txt, file3.txt, file4.txt
file_one = create_files(create_directory("file1_dir"), 'file1.txt')
file_two = create_files(create_directory("file2_dir"), 'file2.txt')
file_three = create_files(create_directory("file3_dir"), 'file3.txt')
file_four = create_files(create_directory("file4_dir"), 'file4.txt')
# Step 2: Creating destination_directory:
destination_dir = create_directory('destination_directory')
files = [file_one, file_two, file_three, file_four]
# Step 3: Moving Your Files:
for file in files:
shutil.move(file, destination_dir)
if __name__ == "__main__":
main()

how to check if path exist and copy folders and files using python

I have a python script that must check first if folder exist in giving path then if exist delete the existing one then copy the new one from the source. if does't exist just copy the new folder.
the problem is that in the source path if i have folder the system will check if the folder exist in the destination and delete and copy if exist.
what i want is to just check for one folder name "test" and then if does't exist copy the new folder if exist delete and copy.
code:
import os
import shutil
from os import path
import datetime
src = "I:/"
src2 = "I:/test"
dst = "C:/Users/LT GM/Desktop/test/"
dst2 = "C:/Users/LT GM/Documents/"
dst3 = "C:/Users/LT GM/Documents/Visual Studio 2017"
def main():
copy()
def copy():
#go through the src files and folders
for root,dirs,files in os.walk(src):
try:
for folder in dirs:
#return folder name
full_folder_name = os.path.join(src, folder)
print("folder : ",full_folder_name)
#check if folder exits
if os.path.exists(dst):
print("folder exist")
#delete folder
shutil.rmtree(dst)
print("the deleted folder is :{0}".format(dst))
#copy the folder as it is (folder with the files)
copieddst = shutil.copytree(src2,dst)
print("copy of the folder is done :{0}".format(copieddst))
else:
print("folder does Not Exist")
#copy the folder as it is (folder with the files)
copieddst = shutil.copytree(src2,dst)
print("copy of the folder is done :{0}".format(copieddst))
except Exception as e:
print(e)
try:
for name in files:
full_file_name = os.path.join(src, name)
print("files: ",full_file_name)
#check for pdf extension
if name.endswith("pdf"):
#copy files
shutil.copy(full_file_name, dst2)
#check for doc & docx extension
elif name.endswith("docx") or name.endswith("doc"):
#copy files
shutil.copy(full_file_name, dst3)
print("word files done")
print("pdf files done")
except Exception as e:
print(e)
if __name__=="__main__":
main()
why do you even check? Just rmtree the destination and ignore the error if it doesn't exist. You're not getting any significant saving by first checking, you're just making your code more complex.
why do you delete src for every folder you're copying? Just delete it once before the loop
also you should probably copy the sub-folders of src in sub-folders of dst rather than dump everything in src
os.walk will recursively walks through all the directories under the root (and thus their directories, and theirs, ...), that really doesn't seem to be what you want here,
your path management is weird as hell, why do you have two different sources and three destinations used completely inconsistently?

How do I delete all folders within a folder except for one in python?

I am modifying a wizard in Kodi and I would like the wizard to delete all folders contained within the "addons" directory without deleting my wizard.
The directory of the folder will be using the "special://" function built into Kodi. I would like to delete everything inside of "special://home/addons" except for the folder named "plugin.video.spartan0.12.0"
I know that python needs to use "xbmc.translatePath" function to recognize the folder path, but I don't know how to delete everything in the folder without deleting "plugin.video.spartan0.12.0"
Any help would be appreciated.
Here is what I currently have
import os
dirPath = "C:\Users\Authorized User\AppData\Roaming\Kodi\addons"
fileList = os.listdir(dirPath)
for fileName in fileList:
os.remove(dirPath+"/"+fileName)
This is probably overkill (and a little sloppy), but it worked for me:
import os
import shutil
#----------------------------------------------------------------------
def remove(path):
"""
Remove the file or directory
"""
if os.path.isdir(path):
try:
shutil.rmtree(path)
except OSError:
print "Unable to remove folder: %s" % path
else:
try:
if os.path.exists(path):
os.remove(path)
except OSError:
print "Unable to remove file: %s" % path
#----------------------------------------------------------------------
def cleanup(dirpath, folder_to_exclude):
for root, dirs, files in os.walk(dirpath, topdown=True):
for file_ in files:
full_path = os.path.join(root, file_)
if folder_to_exclude not in full_path:
print 'removing -> ' + full_path
remove(full_path)
for folder in dirs:
full_path = os.path.join(root, folder)
if folder_to_exclude not in full_path:
remove(full_path)
if __name__ == '__main__':
cleanup(r'c\path\to\addons', 'plugin.video.spartan0.12.0')

For file in directories, rename file to directoryname

I have let's say 5 directories, let's call them dir1, dir2, dir3, dir4, dir5.
These are all in the current directory. Each of them contains 1 files called title.mkv. I want to rename the files to the directory name they are in, ie the file title.mkv in dir1, I want to rename to dir1.mkv.
I also want to then move the file to another folder. What python tools do I need for this besides os and glob?
If you have the full filename and directory, to rename the files, you can use
import os
f_name = 'E:/temp/nuke.mkv'
# Removes '/' at the end of string
while f_name.endswith('/'):
f_name = f_name[:-1]
# Generates List Containing Directories and File Name
f_name_split = f_name.split('/')
f_path = ''
# Iterates Through f_name_split, adding directories to new_f_path
for i in range(len(f_name_split)-1):
f_path += f_name_split[i] + '/'
# Makes New Name Based On Folder Name
new_name = f_name_split[-2] + '.mkv'
# Gets The Old File Name
f_name = f_name_split[-1]
# Renames The File
os.rename(f_path + f_name, f_path + new_name)
To go through all of the directories, you could do it recursively, have the system output it to a file [windows: dir /s /b /a > file.txt], or use os.walk. To move a file, you can use os.rename(source, destination)
The following should work, although you will have problems if there is more than one file per source folder:
import os
source_folder = r"c:\my_source_folder"
target_folder = r"c:\target_folder"
for directory_path, dirs, files in os.walk(source_folder):
# Current directory name
directory = os.path.split(directory_path)[1]
# Ensure only MKV files are processed
files = [file for file in files if os.path.splitext(file)[1].lower() == '.mkv']
# Rename each file
for file in files:
source = os.path.join(directory_path, file)
target = os.path.join(target_folder, directory + ".mkv")
try:
os.rename(source, target)
except OSError:
print "Failed to rename: {} to {}".format(source, target)
It will search all sub folders from the source folder and use the current folder name for the target name.
The following function uses shutil.move, which moves across filesystem and has overwrite protection in case destination file exists. File name can be relative.
from os.path import basename, dirname, isfile, abspath, splitext
from shutil import move
def rename_to_dirname_and_move(name, dst, overwrite=False, verbose=False):
"""renames 'name' to its directory name, keeping its extension
intact and moves to 'dst' directory across filesystem
"""
if not isfile(name):
raise ValueError("{} is not a file or doesn't exist".format(name))
abs_name = abspath(name)
dir_name = basename(dirname(abs_name))
new_name = '{}{}'.format(dir_name, splitext(name)[1])
dst_name = os.path.join(dst, new_name)
if not overwrite and isfile(dst_name):
raise OSError('file {} exists'.format(dst_name))
try:
move(abs_name, dst_name)
except Exception as e:
print("Can't move {} to {}, error: {}".format(abs_name, dst_name,e))
else:
if verbose:
print('Moved {} to {}'.format(abs_name, dst_name))

Categories