OSError: Directory not empty raised, how to fix? - python

I'm just trying to write a little application that takes a value from a file named 'DATA.DAT' and renames the folder which contains that file with that value.
The .py script runs in another folder and allows the user to define the path. To give you a better idea, the user defined path must be like (on a mac) '/Users/User/Desktop/FOLDER' and 'FOLDER' should contain 'DATA.DAT'.
That's how a little part of the source code looks like:
try:
data = open('DATA.DAT').read()
data_data = data[12:17]
path_paths = path.rsplit('/')
basepath = '/'.join(path_paths[:-1])
chdir(basepath)
if path_paths[-1] <> data_data:
rename(path_paths[-1], data_data)
raw_input('Folder name has been corrected! Thank you.')
quit()
else:
print('Folder name was already correct! Thank you.')
quit()
except IndexError:
raw_input('ERROR!')
quit()
Well, it works; but it raise and exception when 'FOLDER' contains more than one file (actually, 'FOLDER' should contain just 'DATA.DAT' and other folders. That doesn't give problems.)...
Traceback (most recent call last):
File "/Users/User/Desktop/example.py", line 72, in <module>
rename(path_paths[-1], data_data)
OSError: [Errno 66] Directory not empty
Just to prevent that this happens, is there a way to fix it? Thanks.

Edit: The right tool is shutil.move:
shutil.move(path_paths[-1], data_data)
assuming path_paths[-1] is the absolute directory you want to rename, and data_data is the absolute directory name you want to rename it to.
The destination directory must not already exist for this to work. The two locations don't need to be on the same filesystem.
Old answer: Use os.renames instead of os.rename.
It will recursively create any needed directories.

It is much easier to use shutil.

Althoug a decade later.. is possible to replace the way for split path
path_paths = path.rsplit('/')
for
path_paths = os.path.split(path)[1]
And for renaming problem:
os.rename('myfolder/oldname', 'myfolder/newname')

Related

How to use the file path as the source parameter from os.walk to copy files

Okay, so I'm not sure how to get python to use the path to a file that it found through an os.walk function as the source parameter for the shutil.copy(source, destination) arguments.
My code example is this
for folderName, subfolders, filenames in os.walk('/Users/me/Documents'):
print('The current folder is '+folderName)
for subfolder in subfolders:
print('SUBFOLDER OF '+folderName+": "+subfolder)
for filename in filenames:
print("FILE INSIDE "+folderName+": "+filename)
if filename.endswith('.txt'):
os.chdir(filename)
shutil.copy(filename, '/Users/me/Documents/School/IT 145/Text Files')
print("")
If the file has a .txt extension, I would like python to copy that file to the specified folder.
My error message I get is this
The current folder is /Users/me/Documents/Text Files
FILE INSIDE /Users/me/Documents/Text Files: guest.txt
Traceback (most recent call last):
File "/Users/me/Documents/School/IT 145/Programming Work/os_walk.py", line 16, in <module>
os.chdir(filename)
FileNotFoundError: [Errno 2] No such file or directory: 'guest.txt'
From what I understand, python is going back to the current working directory to do the shutil.copy, but I don't understand why if I pass it the file path that it just found it won't use that as the source path for the file to copy.
This is my first ever python programming class, and really my first brush with python all, so any teaching thoughts would be greatly appreciated. Thank you very much.
Your current code never leaves its original working directory. You can verify this by running:
print(os.getcwd())
Your os.walk() does not change the current directory (CWD).
Your attempt at changing the CWD:
os.chdir(filename)
does not work since filename is a file name and not a directory.
os.chdir(folderName)
would work.
You could use the approach of changing into the directory just to copy the file. But, you can't be doing that it every iteration of your loop, either -- only on the first. Or, better yet, you could change into the directory at the start. In any case, I advice against this approach since its an unnecessary overhead.
Instead, just prefix the filename with its parent directory -- i.e. folderName when you call shutil.copy().
For example:
shutil.copy(os.path.join(folderName, filename), '/Users/me/Documents/School/IT 145/Text Files')
Side note for readability:
Put '/Users/me/Documents' and '/Users/me/Documents/School/IT 145/Text Files' into named variables -- which makes it easier to read, change and/or reuse if needed.
Side note for portability:
Aim to use os.path.join() instead of using / for the directory separator.

python: zipfile.ZipFile No such file or directory

There is folder path:
P:\\2018\\Archive\\
There are many zipfiles I want to create programmatically, but am starting with test. I will name this test zip file "CO_007_II.zip" and will attempt to create in above location:
import zipfile as zp
with zp.ZipFile("P:\\2018\\Archive\\CO_007_II.zip",'w') as myzip:
myzip.write(r"P:\2018\CO_007_II")
But I get error!
...
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
File "C:\Python27\ArcGIS10.2\lib\zipfile.py", line 752, in __init__
self.fp = open(file, modeDict[mode])
IOError: [Errno 2] No such file or directory: 'P:\\2018\\Archive\\CO_007_II.zip'
Is this not method for creating new zipfile? I know file does not exist. Is why I am using 'w' mode, no?
This is documentation:
https://docs.python.org/3/library/zipfile.html
It says:
'w' to truncate and write a new file
Example on documentation page:
with ZipFile('spam.zip', 'w') as myzip:
myzip.write('eggs.txt')
code worked two days ago to create new zip file but did not add folder. Today nothing works! Why not? All paths valid. How do I create new zip file with python and add folders to it?
I also encountered a similar issue and came here looking for answers. Since this was the top hit, I'll add what I discovered.
The answer provided by #metatoaster didn't work for me, when stepping through the code I found that the path returned true to isdir.
In my case, the path length exceeded the Windows max path length (260 chars) which was causing it to fail despite the folder path being valid.
Hope that helps someone else down the line!
The only way this could be reproduced was to create a zipfile in a directory that does NOT exist yet. The only way to be sure (you cannot trust a file manager; only way to verify is to check from within the program itself) is to assign the desired path of the new zip file to a variable (e.g. path), and then call isdir(dirname(path)). For example:
from os.path import isdir
from os.path import dirname
target = "P:\\2018\\Archive\\CO_007_II.zip"
if not isdir(dirname(target)):
print('cannot create zipfile because target does not exists')
else:
# create the zipfile
I had the same issue. It was the long path. I solved by adding this //?/C at the beginning of the path
path = r"//?/C:\Users\Camilo\Proyectos"

Why do I get a Errno 1 Operation not permitted when the folder is created with full read/write permissions for everyone in Python?

So I am trying to make my very first python program to automate a task that I have. The first snippet of code is from a python script that makes a new folder at a pre-specified destination and then moves files from their original location to the new folder. This part works. The folder is created like so:
os.makedirs(new_folder, 0o777)
new_folder stores the name, given by the user, of the folder to be created.
The next snippet of code is from another script that does the opposite. It takes the files from the new folder and moves them back to the original folder and it does this successfully. However what doesn't work is what is supposed to happen next. Once moved back, it is supposed to delete the new folder with its content. I tried doing it with this code:
os.chdir(new_path)
os.remove(folder_name)
og_path is just a variable that stores the path of the new folder which should be deleted. folder_name stores well...the folder's name
When I run the full code of the second script everything works; however when it reaches:
os.remove(folder_name)
It gives me this error:
Traceback (most recent call last):
File "/Users/TVM/Desktop/python/move_file/move_file_reverse.py", line 25, in <module>
os.remove(folder_name)
PermissionError: [Errno 1] Operation not permitted: 'lab3'
Additional Variable Information:
new_folder = "lab3"
folder_name = "lab3"
new_path = "/Users/TVM/Desktop/python/move_file/newloc"
The folder called lab3 is in the folder newloc
You should use os.rmdir instead of os.remove.
os.mkdir('mydir')
os.rmdir('mydir')
os.path.exists('mydir')
In case if the directory is not empty and you would like to get rid of the whole directory tree starting from the directory you should use:
shutil.rmtree('mydir')
In the comments #ShadowRanger suggest to use shutil.rmtree()
I replaced os.remove() with shutil.rmtree() and it worked. Thank you very much #ShadowRanger.

How to append a record in a file

I have tried to append a record on the next line in the file using the following code(please note that the file has been created already). But, it does not insert any records at all. The file remains empty.
with open(utmppath+'/'+tmpfile, "a") as myfile:
myfile.write(record+'\n')
myfile.close()
Any suggestion would be great. Thanks
Check additionally if you set your path correctly:
import os
path = utmppath+'/'+tmpfile
assert os.path.isfile(path), path
The assertion checks if the file exists and raises an AssertionError if you used a wrong path. Additionally the used path is included in the error message thanks to the variable
after the comma.
Additionally I recommend you to join files with the help of os.path.join and os.path.abspath. os.path.join concatenates path strings correctly for you and os.path.abspath creates an absolute path.
path = os.path.join(utmppath, tmpfile)
Let's say the wished file is in the same directory like your script and called your_output.txt - you can use this:
path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'your_output.txt'))
By the way, __file__ gives you the name of your script file.

Error while using listdir in Python

I'm trying to get the list of files in a particular directory and count the number of files in the directory. I always get the following error:
WindowsError: [Error 3] The system cannot find the path specified: '/client_side/*.*'
My code is:
print len([name for name in os.listdir('/client_side/') if os.path.isfile(name)])
I followed the code example given here.
I am running the Python script on Pyscripter and the directory /client_side/ do exists. My python code is in the root folder and has a sub-folder called "client_side". Can someone help me out on this?
This error occurs when you use os.listdir on a path which does not refer to an existing path.
For example:
>>> os.listdir('Some directory does not exist')
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
WindowsError: [Error 3] : 'Some directory does not exist/*.*'
If you want to use os.listdir, you need to either guarantee the existence of the path that you would use, or use os.path.exists to check the existence first.
if os.path.exists('/client_side/'):
do something
else:
do something
Suppose your current working directory is c:\foobar, os.listdir('/client_side/') is equivalent to os.listdir('c:/client_side'), while os.listdir('client_side/') is equivalent to os.listdir('c:/foobar/client_side'). If your client_side directory is not in the root, such error will occur when using os.listdir.
For your 0 ouput problem, let us recall os.listdir(path)
Return a list containing the names of the entries in the directory given by path. The list is in arbitrary order. It does not include the special entries '.' and '..' even if they are present in the directory.
and os.path.isfile(path).
Return True if path is an existing regular file. This follows symbolic links, so both islink() and isfile() can be true for the same path.
listdir returns neither the absolute paths nor relative paths, but a list of the name of your files, while isfile requires path. Therefore, all of those names would yield False.
To obtain the path, we can either use os.path.join , concat two strings directly.
print ([name for name in os.listdir(path)
if os.path.isfile(os.path.join(path, name))])
Or
print ([name for name in os.listdir('client_side/')
if os.path.isfile('client_side/' + name)])
I decided to change the code into:
def numOfFiles(path):
return len(next(os.walk(path))[2])
and use the following the call the code:
print numOfFiles("client_side")
Many thanks to everyone who told me how to pass the windows directory correctly in Python and to nrao91 in here for providing the function code.
EDIT: Thank you eryksun for correcting my code!
Two things:
os.listdir() does not do a glob pattern matching, use the glob module for that
probably you do not have a directory called '/client_side/*.*', but maybe one
without the . in the name
The syntax you used works fine, if the directory you look for exists, but there is no directory called '/client_side/.'.
In addition, be careful if using Python 2.x and os.listdir, as the results on windows are different when you use u'/client_side/' and just '/client_side'.
You can do just
os.listdir('client_side')
without slashes.
As I can see a WindowsError, Just wondering if this has something to do with the '/' in windows ! Ideally, on windows, you should have something like os.path.join('C:','client_side')
You want:
print len([name for name in os.listdir('./client_side/') if os.path.isfile(name)])
with a "." before "/client_side/".
The dot means the current path where you are working (i.e. from where you are calling your code), so "./client_side/" represents the path you want, which is specified relatively to your current directory.
If you write only "/client_side/", in unix, the program would look for a folder in the root of the system, instead of the folder that you want.
If you just want to see all the files in the directory where your script is located, you can use os.path.dirname(sys.argv[0]). This will give the path of the directory where your script is.
Then, with fnmatch function you can obtain the list of files in that directory with a name and/or extension specified in the filenamevariable.
import os,sys
from fnmatch import fnmatch
directory = os.path.dirname(sys.argv[0]) #this determines the directory
file_name= "*" #if you want the python files only, change "*" to "*.py"
for path, subdirs, files in os.walk(directory):
for name in files:
if fnmatch(name, file_name):
print (os.path.join(path, name))
I hope this helps.
Checking for existence is subject to a race. Better to handle the error (beg forgiveness instead of ask permission). Plus, in Python 3 you can suppress errors. Use suppress from contextlib:
with suppress(FileNotFoundError):
for name in os.listdir('foo'):
print(name)

Categories

Resources