Transfering files from one directory to another via python - python

I'm trying to move multiple files from one directory to another.
The function I'm trying to make should move files if they begin with a value in sample_list. My issue is that there are multiple files which begins with a value in sample_list, this seems to be causing issues for shutil.
import shutil
import os
source = './train/'
dest1 = './test/'
files = [
'195_reg_6762_1540.npz',
'1369_reg_7652_-2532.npz',
'195_reg_1947_-484.npz',
'1336_reg_6209_1217.npz',
'1198_reg_3784_-934.npz',
'12_reg_3992_-10.npz',
'1369_reg_3214_-91.npz']
test_samples = [195, 1493, 409, 339, 12, 1336]
#Move files which begin with values in test_samples [edited orig post to fix typo]
for f in files:
for i in test_samples:
if (f.startswith(str(i))):
shutil.move(source+f, dest1)
Raises the error:
File "/home/usr/anaconda3/lib/python3.7/shutil.py", line 564, in move
raise Error("Destination path '%s' already exists" % real_dst)
Error: Destination path '/home/usr/Documents/project/data/test/195_reg_1947_-484.npz' already exists
It always fails if there is more than one file with a value in test samples to move.
What would be the correct way to move files which begin with values in test_samples from source directory to target directory.

This occurs when you've already successfully run the script (or parts of it once). Once the file exists in the destination directory, shutil throws an exception if you try to replace it.
See this modification that checks if the file already exists in the destination directory and, if so, deletes it and moves it back from the origin directory (note that the file must exist again in the origin directory). [Do you mean to copy instead of move?]
for f in files:
for i in test_samples:
if (f.startswith(str(i))):
if not os.path.exists(dest1+f):
shutil.move(source+f, dest1)
else:
os.remove(dest1+f)
shutil.move(source+f,dest1)

Related

How to move file from a folder to its sub folder?

I'm working with Python and have to move files from a folder to its sub-folder. I tried using shutil.move(), but it gives an error:
Cannot move a directory '%s' into itself
Here's the code:
for file in your_files:
if file in images:
shutil.move(your_folder, images_folder)
elif file in docs:
shutil.move(your_folder, docs_folder)
elif file in texts:
shutil.move(your_folder, texts_folder)
else:
shutil.move(your_folder, others_folder)
images_folder, docs_folder, texts_folder and others_folder are all sub-folders of your_folder.
How do I move files from your_folder to the corresponding sub-folders?
Everything is a file: A directory is a file. The destination directory is a file in the source folder.
You are trying to move the destination folder into it self.
You could:
Add an additional elif, to catch it and do nothing.
Ignore it.

No such file or directory error in python while looping through several files

We are using a function to match a file pattern and if it matches we are running some jobs and eventually removing the file form the folder. But the file pattern match code is failing with "FileNotFoundError: [Errno 2] No such file or directory" when the for loop is running and some of the files are removed, this is happening in so less time that we are not able to replicate the issue in lower environment. Any idea how to catch the error or resolve it. In this case 'ABCD.XAF.XYJ250.A252.dat' file was present in the folder but removed as part of some other job.
def poke(self, context):
full_path = self.filepath
file_pattern = re.compile(self.filepattern)
os.chdir(full_path)
for files in sorted(os.listdir(full_path),key=os.path.getmtime):
if not re.match(file_pattern, files):
self.log.info(files)
self.log.info(file_pattern)
else:
print("File Sensed "+files)
return True
return False
Error:
File "File_Sensor_Operator.py", line 25, in poke
for files in sorted(os.listdir(full_path),key=os.path.getmtime):
File "/usr/lib64/python3.6/genericpath.py", line 55, in getmtime
return os.stat(filename).st_mtime
FileNotFoundError: [Errno 2] No such file or directory: 'ABCD.XAF.XYJ250.A252.dat'
IIUC, the error is happening because after the for loop starts, you have removed one of the files which means that it is no longer in the iterable returned bysorted(os.listdir(full_path),key=os.path.getmtime) which then throws the error.
So I think it should go away if you change that section of your code to this:
all_files = sorted(os.listdir(full_path),key=os.path.getmtime)
for files in all_files:
if not re.match(file_pattern, files):
That way the iterable is assigned to a variable so the state is preserved as you loop through it.
Your issue is that you collect all the files, delete one, then try to sort them by each files attributes (whereof one doesn't exist anymore)
import os
with open("dat.dat", "w+"):
pass
file_list = os.listdir(os.path.dirname(__file__))
os.remove("dat.dat")
for file_name in sorted(file_list, key=os.path.getmtime):
print(file_name)
You can fix it by assigning the filenames and attributes to a variable before sorting.
import os
with open("dat.dat", "w+"):
pass
file_list = {
filename:os.path.getmtime(filename)
for filename in os.listdir(os.path.dirname(__file__))
if os.path.exists(filename)
}
os.remove("dat.dat")
for file_name in sorted(file_list.keys(), key=file_list.get):
print(file_name)

Python: folder creation when copying files

I'm trying to create a shell script that will copy files from one computer (employee's old computer) to another (employee's new computer). I have it to the point where I can copy files over, thanks to the lovely people here, but I'm running into a problem - if I'm going from, say, this directory that has 2 files:
C:\Users\specificuser\Documents\Test Folder
....to this directory...
C:\Users\specificuser\Desktop
...I see the files show up on the Desktop, but the folder those files were in (Test Folder) isn't created.
Here is the copy function I'm using:
#copy function
def dir_copy(srcpath, dstpath):
#if the destination path doesn't exist, create it
if not os.path.exists(dstpath):
os.makedir(dstpath)
#tag each file to the source path to create the file path
for file in os.listdir(srcpath):
srcfile = os.path.join(srcpath, file)
dstfile = os.path.join(dstpath, file)
#if the source file path is a directory, copy the directory
if os.path.isdir(srcfile):
dir_copy(srcfile, dstfile)
else: #if the source file path is just a file, copy the file
shutil.copyfile(srcfile, dstfile)
I know I need to create the directory on the destination, I'm just not quite sure how to do it.
Edit: I found that I had a type (os.makedir instead of os.mkdir). I tested it, and it creates directories like it's supposed to. HOWEVER I'd like it to create the directory one level up from where it's starting. For example, in Test Folder there is Sub Test Folder. It has created Sub Test Folder but won't create Test Folder because Test Folder is not part of the dstpath. Does that make sense?
You might want to look at shutil.copytree(). It performs the recursive copy functionality, including directories, that you're looking for. So, for a basic recursive copy, you could just run:
shutil.copytree(srcpath, dstpath)
However, to accomplish your goal of copying the source directory to the destination directory, creating the source directory inside of the destination directory in the process, you could use something like this:
import os
import shutil
def dir_copy(srcpath, dstdir):
dirname = os.path.basename(srcpath)
dstpath = os.path.join(dstdir, dirname)
shutil.copytree(srcpath, dstpath)
Note that your srcpath must not contain a slash at the end for this to work. Also, the result of joining the destination directory and the source directory name must not already exist, or copytree will fail.
This is a common problem with file copy... do you intend to just copy the contents of the folder or do you want the folder itself copied. Copy utilities typically have a flag for this and you can too. I use os.makedirs so that any intermediate directories are created also.
#copy function
def dir_copy(srcpath, dstpath, include_directory=False):
if include_directory:
dstpath = os.path.join(dstpath, os.path.basename(srcpath))
os.makedirs(dstpath, exist_ok=True)
#tag each file to the source path to create the file path
for file in os.listdir(srcpath):
srcfile = os.path.join(srcpath, file)
dstfile = os.path.join(dstpath, file)
#if the source file path is a directory, copy the directory
if os.path.isdir(srcfile):
dir_copy(srcfile, dstfile)
else: #if the source file path is just a file, copy the file
shutil.copyfile(srcfile, dstfile)
import shutil
import os
def dir_copy(srcpath, dstpath):
try:
shutil.copytree(srcpath, dstpath)
except shutil.Error as e:
print('Directory not copied. Error: %s' % e)
except OSError as e:
print('Directory not copied. Error: %s' % e)
dir_copy('/home/sergey/test1', '/home/sergey/test2')
I use this script to backup (copy) my working folder. It will skip large files, keep folder structure (hierarchy) and create destination folders if they don't exist.
import os
import shutil
for root, dirs, files in os.walk(the_folder_copy_from):
for name in files:
if os.path.getsize(os.path.join(root, name))<10*1024*1024:
target=os.path.join("backup", os.path.relpath(os.path.join(root, name),start=the_folder_copy_from))
print(target)
os.makedirs(os.path.dirname(target),exist_ok=True)
shutil.copy(src=os.path.join(root, name),dst=target)
print("Done")

IOError: [Errno 13] Permission denied: Bulk renaming script

This is one of my first python scripts designed to go into a directory and rename all the files of a certain extension to the same thing. For instance, go into a music directory and change the name of all the album artwork files to something like folder.jpg so that they're easily recognized and displayed by music playing software like foobar2000.
I'm currently getting the error in the title. I've tried:
os.chmod(pathname, 0777)
and
os.chmod(pathname, stat.S_IWOTH)
to allow other entities to edit the directory I'm looking at, but the error remains. I'm not too familiar with Windows's permissions system or with Python so this is mystifying me. Any idea where I'm going wrong?
#Changes file names in every subdirectory of the target directory
import os
import sys
import shutil
#Get target path
pathname = raw_input('Enter path for music directory (ex. C:\\Music): ')
try:
os.chdir(pathname)
except:
print('Failed. Invalid directory?')
sys.exit()
#Get variables for renaming
fn = raw_input('Enter desired file name for all converted files: ')
ft = raw_input('Enter the file extension you want the program to look for (ex. .jpg): ')
outname = fn + ft
#Create path tree
for path, subdirs, files in os.walk (pathname):
#Search tree for files with defined extention
for name in files:
if name.lower().endswith(ft):
#Rename the files
src = os.path.join(path, name)
print (src)
dst = os.path.join(path, outname)
print dst
shutil.move(src, dst)
print('Complete')
A second more benign issue is that when I use a print statement to check on what files are being edited, it seems that before the first .jpg is attempted, the program processes and renamed a file called d:\test\folder.jpg which doesn't exist. This seems to succeed and the program fails in the last loop the second time through, when an existing file is processed. The program runs like this:
>>> ================================ RESTART ================================
>>>
Enter path for music directory (ex. C:\Music): d:\test
Enter desired file name for all converted files: folder
Enter the file extension you want the program to look for (ex. .jpg): .jpg
d:\test\folder.jpg
d:\test\folder.jpg
d:\test\Anathema\Alternative 4\AA.jpg
d:\test\Anathema\Alternative 4\folder.jpg
Traceback (most recent call last):
File "D:\Documents\Programming\Python scripts\Actually useful\bulk_filename_changer.py", line 29, in <module>
shutil.move(src, dst)
File "C:\Python27\lib\shutil.py", line 301, in move
copy2(src, real_dst)
File "C:\Python27\lib\shutil.py", line 130, in copy2
copyfile(src, dst)
File "C:\Python27\lib\shutil.py", line 83, in copyfile
with open(dst, 'wb') as fdst:
IOError: [Errno 13] Permission denied: 'd:\\test\\Anathema\\Alternative 4\\folder.jpg'
>>>
The glitch seems to be benign because it doesn't cause an error, but it might be related to an error I have in the code that leads to the IOError I get when the first "real" file is processed. Beats me...
I am assuming that d: is not a CD drive or something not writable. If so then have you checked the properties of your files? Are any of them read only? There would also need to be more than one of the file type in the folder to cause this, I believe.

Backup File Script

I am writing a script to backup files from one dir(Master) to another dir(Clone).
And the script will monitor the two directories.
If a file inside clone is missing then the script will copy the missing file from Master to
Clone.Now I have a problem creating the missing folder.
I have read the documentation and found that shutil.copyfile will create a dir if the
dir doesn't exist.But I am getting an IOError message showing that the destination dir
is not exist.Below is the code.
import os,shutil,hashlib
master="C:\Users\Will Yan\Desktop\Master"
client="D:\Clone"
if(os.path.exists(client)):
print "PATH EXISTS"
else:
print "PATH Doesn't exists copying"
shutil.copytree(master,client)
def walkLocation(location,option):
aList = []
for(path,dirs,files) in os.walk(location):
for i in files:
if option == "path":
aList.append(path+"/"+i)
else:
aList.append(i)
return aList
def getPaths(location):
paths=[]
files=[]
result =[]
paths = walkLocation(location,'path')
files = walkLocation(location,'files')
result.append(paths)
result.append(files)
return result
ma=walkLocation(master,"path")
cl=walkLocation(client,"path")
maf=walkLocation(master,"a")
clf=walkLocation(client,"a")
for i in range(len(ma)):
count = 0
for j in range(len(cl)):
if maf[i]==clf[j]:
break
else:
count= count+1
if count==len(cl):
dirStep1=ma[i][ma[i].find("Master")::]
dirStep2=dirStep1.replace("Master",client)
shutil.copyfile(ma[i],dirStep2)
Can anyone tell me where did I do wrong?
Thanks
Sorry, but the documentation doesn't say that. Here's a reproduction of the full documentation for the function:
shutil.copyfile(src, dst)
Copy the
contents (no metadata) of the file
named src to a file named dst. dst
must be the complete target file name;
look at copy() for a copy that accepts
a target directory path. If src and
dst are the same files, Error is
raised. The destination location must
be writable; otherwise, an IOError
exception will be raised. If dst
already exists, it will be replaced.
Special files such as character or
block devices and pipes cannot be
copied with this function. src and dst
are path names given as strings.
So you have to create the directory yourself.

Categories