I am trying to write a program to categorize into folders a large amount of files according to their respective groups indicated in the file name. I wrote the followin code, but when I run it it gives me a file not found error, even though the file is in the given path. I'd appreciate any help in figuring out what is wrong.
import os
old_dir = '/Users/User/Desktop/MyFolder'
for f in os.listdir(old_dir):
file_name, file_ext = os.path.splitext(f)
file_name.split('-')
split_file_name = file_name.split('-')
new_dir = os.path.join(old_dir,
'-'.join(split_file_name[:3]),
split_file_name[5],
f)
os.rename(os.path.join(old_dir, f), new_dir)
Here's the error:
Traceback (most recent call last):
File "/Users/User/Documents/Sort Files into Folders/Sort Files into Folders.py", line 19, in <module>
os.rename(os.path.join(old_dir, f), new_dir)
FileNotFoundError: [Errno 2] No such file or directory: '/Users/User/Desktop/MyFolder/AHA35-3_30x1_12-31-7d-g1a1-ArmPro.jpg' -> '/Users/User/Desktop/MyFolder/AHA35-3_30x1_12-31/ArmPro/AHA35-3_30x1_12-31-7d-g1a1-ArmPro.jpg
os.rename does not automatically create new directories (recursively), if the new name happens to be a filename in a directory that does not exist.
To create the directories first, you can (in Python 3) use:
os.makedirs(dirname, exist_ok=True)
where dirname can contain subdirectories (existing or not).
Alternatively, use os.renames, that can handle new and intermediate directories. From the documentation:
Recursive directory or file renaming function. Works like rename(), except creation of any intermediate directories needed to make the new pathname good is attempted first
os.rename need path, so it should look like:
os.rename(path+old_name, path+new_name)
Related
I'm trying to use a program to read from a file with pi-digits. The program and the text file with the pi-digits are in the same directory, but i still get the error message :
with open('pi_digits.txt') as file_object:
contents = file_object.read()
print(contents.rstrip())
Traceback (most recent call last):
File "C:\Python\Python_Work\python_crash_course\files_and_exceptions\file_reader.py", line 1, in <module>
with open('pi_digits.txt') as file_object:
FileNotFoundError: [Errno 2] No such file or directory: 'pi_digits.txt'
I have looked for a solution but haven't found any.
I found a piece of code which supposedly shows me what the working directory is. I get an output that shows a directory that is 2 steps above the directory i have my programs and text file inside.
import os
cwd = os.getcwd() # Get the current working directory (cwd)
files = os.listdir(cwd) # Get all the files in that directory
print("Files in %r: %s" % (cwd, files))
So when i put the pi text document in the directory that the output is showing (>python_work), the program is working. When it does not work is when the text file is in ">files_and_exceptions" which is the same file the program itself is inside. My directory looks like this when it is not working:
>python_work
>python_crash_course
>files_and_exceptions
file_reader.py
pi_digits.txt
show_working_directory.py
And like this when it is working:
>python_work
pi_digits.txt
>python_crash_course
>files_and_exceptions
file_reader.py
show_working_directory.py
I'm new to python and really appreciate any help.
Thanks!
Relative path (one not starting with a leading /) is relative to some directory. In this case (and generally*), it's relative to the current working directory of the process.
In your case, given the information you've provided, for it would be "python_crash_course/files_and_exceptions/pi_digits.txt" in the first case as you appear to be running the script from python_work directory.
If you know the file to be in the same directory as the script itself, you could also say:
import os.path
...
os.path.join(os.path.dirname(__file__), "pi_digits.txt")
instead of "pi_digits.txt". Or the same using pathlib:
from pathlib import Path
...
Path(__file__).with_name("pi_digits.txt")
Actually unless you have a point to anchor to like the script itself, using relative filename / path (using absolute paths brings its own problems too) in the code directly is rather fragile and in that case getting it as a parameter of a function (and ultimately argument of CLI or script call in general) or alternatively reading it from standard input would be more robust.
* I would not make that an absolute statement, because there are situations and functions that can explicitly provide different anchor point (e.g. os.path.relpath or openat(2); or as another example a symlink target)
I have a bit of code that searches for files in a network share that match a certain keyword. When a match is found, I would like to copy the found files to a different location on the network. The error I'm getting is as follows:
Traceback (most recent call last):
File "C:/Users/user.name/PycharmProjects/SearchDirectory/Sub-Search.py", line 15, in <module>
shutil.copy(path+name, dest)
File "C:\Python27\lib\shutil.py", line 119, in copy
copyfile(src, dst)
File "C:\Python27\lib\shutil.py", line 82, in copyfile
with open(src, 'rb') as fsrc:
IOError: [Errno 2] No such file or directory: '//server/otheruser$/Document (user).docx'
I believe it's because I'm trying to copy the found file without specifying its direct path, since some of the files are found in subfolders. If so, how can I store the direct path to a file when it matches the keyword? Here is the code I have so far:
import os
import shutil
dest = '//dbserver/user.name$/Reports/User'
path = '//dbserver/User$/'
keyword = 'report'
print 'Starting'
for root, dirs, files in os.walk(path):
for name in files:
if keyword in name.lower():
shutil.copy(path+name, dest)
print name
print 'Done'
PS. The user folder being accessed is hidden, hence the $.
Looking at the docs for os.walk, your error is most likely that you are not including the full path. To avoid having to worry about things like trailing slashes and OS/specific path separators, you should also consider using os.path.join.
Replace path+name with os.path.join(root, name). The root element is the path of the subdirectory under path actually containing name, which you are currently omitting from your full path.
You should also replace dest with os.path.join(dest, os.path.relpath(root, path)) if you wish to preserve the directory structure in the destination. os.path.relpath subtracts the path prefix of path from root, allowing you to create the same relative path under dest. If the correct subfolders do not exist, you may want to call os.mkdir or better yet os.makedirs on them as you go:
for root, dirs, files in os.walk(path):
out = os.path.join(dest, os.path.relpath(root, path))
#os.makedirs(out) # You may end up with empty folders if you put this line here
for name in files:
if keyword in name.lower():
os.makedirs(out) # This guarantees that only folders with at least one file get created
shutil.copy(os.path.join(root, name), out)
Finally, look into shutil.copytree, wich does something very similar to what you want. The only disadvantage is that it does not offer the fine level of control for things like filtering that os.walk does (which you are using).
I have this code which lists the files in the directory and parses each one of them with my function.
paths = []
for filename in os.listdir(r"C:\Program Files (x86)\Folder\Folder"):
with open(filename) as f:
paths.append(parse_file(f))
I am getting the error:
File "find.py", line 21, in <module>
with open(filename) as f:
IOError: [Errno 2] No such file or directory: 'file.txt'
This error shows that it saw file.txt because it exist in the folder I specified in os.listdir, I have many more files there. If I delete file.txt it will show the error on a different file.
I also tried to move the files to a directory in my desktop and the script worked fine.
What is the issue I don't understand. I am pretty new to python so forgive me if its dumb question. Thank you!
os.listdir() returns filenames, not paths. Join them with the directory name to make absolute paths:
path = r"C:\Program Files (x86)\Folder\Folder"
for filename in os.listdir(path):
with open(os.path.join(path, filename)) as f:
This is my first time using stack overflow so sorry if i make a mistake.
When trying to run this code it will execute fine and give me my properly renamed files.
import os
a = 0
name_target = raw_input("input the prefix of the files you want enumerated")
for filename in os.listdir("."):
if filename.startswith(name_target):
a = int(a) + 1
a = str(a)
no = filename.__len__() - 4
os.rename(filename, filename[:no] + a + '.txt')
Now this is fine as long as the script exists in the same folder as the files are. But I want to be able to use this script with files which are not in the same folder.
I have found that os.listdir('\some\folder\elsewhere') works fine for other directories but when it comes to renaming them withos.rename the code breaks giving me the message:
Traceback (most recent call last):
File "<string>", line 244, in run_nodebug
File "C:\Users\guy\Desktop\otherfolder\renaming_script.py", line 10, in <module>
os.rename(filename, filename[:no] + a + '.txt')
WindowsError: [Error 2] The system cannot find the file specified`
I have no idea what is wrong here please help me.
The problem is that for other directories, you are getting the directory contents properly but when you try and rename the contents simply by using filenames, the program in fact looks it its own directory, and being unable to find the file, throws an error. Instead you should do something as follows:
os.rename('\some\folder\elsewhere\filename.txt', '\some\folder\elsewhere\filename2.txt')
Or, you can also do the following:
directory = '\some\folder\elsewhere'
os.rename(os.path.join(directory, 'filename.txt'), os.path.join(directory, 'filename2.txt'))
Or, you can also change your working directory as follows:
os.chdir('\some\folder\elsewhere')
An then simply call the os.rename method as if you are in the desired directory
os.rename('filename.txt', 'filenam2.txt')
If you use os.listdir(path), you also have to provide the path in the rename: os.rename(path+filename,path+new_name).
Other option is to use os.chdir(desired_path). With this, your os.rename is fine.
I have the following script:
import os
import stat
curDir = os.getcwd()+'/test'
for (paths, dirs, files) in os.walk(curDir):
for f in files:
if os.stat(f)[stat.ST_SIZE]>0:
print f
and the folder test/:
test_folder:
--test.wav
a.exe
t1
t2
rain.wav
when i run this script with geany it gives the following error:
Traceback (most recent call last):
File "new_folder_deleter.py", line 8, in <module>
if os.stat(f)[stat.ST_SIZE]>0:
OSError: [Errno2] No such file or directory: 'a.exe'
but when I run it with IDLE:
it just prints test.wav in subfolder test_folder
Can anyone explain why it is so and how I can fix it?
P.S:
My aim is to browse all files and delete files with specified sizes.
You need to specify a full path for os.stat, unless the file is in the current working directory. The simplest way to fix this is to change the WD before trying to access the files:
curDir = os.getcwd()+'/test'
os.chdir(curDir)
A more general solution is to pass the full path to os.stat:
if os.stat(os.path.join(paths, f))[stat.ST_SIZE]>0:
print f
I am not quite sure why IDLE does not produce an error here, though.
The filename is only the basename. You need to use os.path.join(path, f).
The list of files that's returned in the files component from os.walk() is just the file names, without the path. Before you can perform any operations on those files (including stat()), you need to reassemble the path to the file.
The os.walk function returns file and directory names relative to current folder, so you need to os.stat(os.path.join(paths, f)).