how to `shutil.move` with readonly files across drives - python

At least on windows, shutil.move a folder containing readonly files to another drive will fail. It fails because move is implemented with a copy followed by a rmtree. In the end, it's the rmtree trying to delete non writable files.
Currently I work around it by first setting the stat.S_IWUSER for all (nested) files, but now I should still restore the original stat afterwards:
def make_tree_writable(source_dir):
for root, dirs, files in os.walk(source_dir):
for name in files:
make_writable(path.join(root, name))
def make_writable(path_):
os.chmod(path_, stat.S_IWUSR)
def movetree_workaround(source_dir, target_dir):
make_tree_writable(source_dir)
shutil.move(source_dir, target_dir)
So I wonder: is this the way? Is there a shutil2 in the making that I could use? Can I be of any help there?

You can do that in two steps: first, use shutil.copytree() to copy the full directory and file structure with appropriate permissions. Then you can change permissions of the source to make sure you have rights to delete stuff, and use shutil.rmtree() to remove the old source.

Related

what does the "shutil.rmtree" do?

I saw the following codes on website:
import tempfile
import shutil
dirpath = tempfile.mkdtemp()
# ... do stuff with dirpath
shutil.rmtree(dirpath)
I know that "shutil.rmtree" is delete an entire directory tree. But why delete the directory just after it was built?
I fond one answer said:"If you use this in a test be sure to remove (shutil.rmtree) the directory because it's not automatically deleted after use." But after I tried, even without "shutil.rmtree", the directory I just built will be deleted after restart computer.
So what does the "shutil.rmtree" do?
The directory is created in a temporary location that your system may choose to delete at some point in the future.
If you know you're done with the temporary directory created, you can remove it yourself using shutil.rmtree immediately.

why shutil.copy and shutil.copy2 create hidden lock files

I need copy certain files (that satisfy some condition) from directory in another directory, but I have a problem , that every time I copy the files into the folder with shutil.copy or shutil.copy2 it creates me the .~lock files, so I'm not able to perform some other functions on this folder
my function to copy the specific files from one folder to another:
def copy_files(path):
path_input = "%input//" % path
path_output="%output//" % path
for i in os.listdir(path_input):
f=os.path.join(path, i)
if f.endswith("t.house.csv"):
shutil.copy(f, path_output) #or shutil.copy2(f, path_output)
So my questions: why it happens and how I can avoid creating of ~lock files? and if I can't avoid, with which methods I can get rid of them?
if one of the files that I copy is open, it will create corresponding ~lock file in the folder of destination! so, maybe it's not the best and smartest way to fix this bug, but by making sure that there are no open files, I can avoid the creating of ~lock files

Python Kivy: Search directory for filetype

There are many ways, to search a dir for containing a string, that's not really my question. But is there something built in for Python Kivy, that allows automatically searching for files (*.mp3) in a directory with subdirs, or do I have to create one on my own?
If I have to do so, how do I get all the files and subdirs in a directory?
Thank you :)
Finally I decided coding the needed function on my own:
import os
def listfiles(path):
files = []
for base, directory, filename in os.walk(path):
for i in range(len(filename)):
files.append(base+"/"+filename[i])
return files
print(listfiles("/path/path/"))
Checking files for extensions should be easy enaugh :)
Unfortunately the process might take very long for bigger directories, so I'm still looking for a different solution.
Check out Kivy kivy.uix.filechooser FileChooserController and its method files
The list of files in the directory specified by path after applying the filters.
files is a read-only ListProperty.
#edit
Here's what I also found in Kivy docs and this one seems even nicer:
from kivy.uix.filechooser import FileSystemLocal
file_system = FileSystemLocal()
file_system.listdir('/path/to/dir') # this returns a list of files in dir
Instead of FileSystemLocal you can also use FileSystemAbstract if you are not going to browse only local files.
files = [] # list with files in directory
suff = ('.mp3', '.wav')
for i in files:
if i.endswith(suff):
print files
Suffixes needs to be tuples for this to work.

Python changing folder permissions [duplicate]

This question already has answers here:
Python changing file permissions when not wanted
(2 answers)
Closed 9 years ago.
for some reason this python script no longer works now. The script changes the folder permission to read only after it has been run? It runs once and deletes all the files in the folder but when it runs again it gets a Windows error 5 Access denied due to the script changing the permissions to read only on the folder. I can't see why it does this or how to avoid it?
The thing is i didn't write this script and know nothing about python. how would you change it to avoid this issue. Please could you give an example with the code in the script, i wouldn't know where to place it. thanks for the help!
import os
import shutil
for root, dirs, files in os.walk(eg.globals.tvzip):
for f in files:
os.remove(os.path.join(root, f))
for d in dirs:
shutil.rmtree(os.path.join(root, d))
for root, dirs, files in os.walk(eg.globals.tvproc):
for f in files:
os.remove(os.path.join(root, f))
for d in dirs:
shutil.rmtree(os.path.join(root, d))
I don't care whether you wrote this code or not, it makes no sense, and trying to make it work without fixing it is a silly idea.
First, if you want to remove an entire directory tree, don't try to walk the tree and remove each subtree before walking it. Just remove the whole tree:
shutil.rmtree(eg.globals.tvzip)
shutil.rmtree(eg.globals.tvproc)
If you want to remove all of the contents of the tree, but not the root itself, don't use os.walk, just os.listdir:
for p in os.listdir(eg.globals.tvzip):
shutil.rmtree(os.path.join(eg.globals.tvzip, p)
for p in os.listdir(eg.globals.tvproc):
shutil.rmtree(os.path.join(eg.globals.tvproc, p)
That will remove any errors caused by your code stepping on its own toes, trying to keep a directory open for its walk and trying to delete it at the same time.
If you still get errors, it could be because some of the files are read-only, but it could just as easily be because some other program has them open. The only way you will be able to debug that is to know which files, so you can examine them.
The exceptions that you get should include the full pathname to the file that failed in their output—in fact, you showed one in one of your other questions:
WindowsError: [Error 5] Access is denied: 'C:\\zDump\\TVzip\\Elem.avi'
So, how do you know what the problem is?
You can open C:\zDump\TVzip in Explorer and look at Elem.avi and see if it's read-only. Or you can use the DOS prompt, if you know how to do that.
To determine whether it's being kept open by another program, you need a third-party tool. The GUI tool Process Explorer and the command-line tool Handle, both from Sysinternals and published by Microsoft, are probably the simplest.
If you want to delete a whole tree of flies, shutil.rmtree will do it for you - you don't need to walk the list of files deleting them.
If you're trying to not delete the top level directory, you should add a check for that. According to the docs, you will be given the top-level directory:
os.walk(top, topdown=True, onerror=None, followlinks=False)
Generate
the file names in a directory tree by walking the tree either top-down
or bottom-up. For each directory in the tree rooted at directory top
(including top itself), it yields a 3-tuple (dirpath, dirnames,
filenames).
Could something else than your script be setting these folders read only? Perhaps you're deleting them, then getting Access Denied because they don't exist, or something else is re-creating them that way?

python zipfile basename

I have some homework that I am trying to complete. I don't want the answer. I'm just having trouble in starting. The work I have tried is not working at all... Can someone please just provide a push in the right direction. I am trying to learn but after trying and trying I need some help.
I know I can you os.path.basename() to get the basename and then add it to the file name but I can't get it together.
Here is the assignment
In this project, write a function that takes a directory path and creates an archive of the directory only. For example, if the same path were used as in the example ("c:\\xxxx\\Archives\\archive_me"), the zipfile would contain archive_me\\groucho, archive_me\\harpo and archive_me\\chico.
The base directory (archive_me in the example above) is the final element of the input, and all paths recorded in the zipfile should start with the base directory.
If the directory contains sub-directories, the sub-directory names and any files in the sub-directories should not be included. (Hint: You can use isfile() to determine if a filename represents a regular file and not a directory.)
Thanks again any direction would be great.
It would help to know what you tried yourself, so I'm only giving a few pointers to methods in the standard libraries:
os.listdir to get the a list of files and folders under a given directory (beware, it returns only the file/folder name, not the full path!)
os.path.isfile as mentioned in the assignment to check if a given path represents a file or a folder
os.path.isdir, the opposite of os.path.isfile (thanks inspectorG4adget)
os.path.join to join a filename with the basedir without having to worry about slashes and delimiters
ZipFile for handling, well, zip files
zipFile.write to write the files found to the zip
I'm not sure you'll need all of those, but it doesn't hurt knowing they exist.

Categories