Python add prefix to file names inside a directory - python

I need to add a prefix to file names within a directory. Whenever I try to do it though, it tries to add the prefix to the beginning of the file path. That won't work. I have a few hundred files that I need to change, and I've been stuck on this for a while. Have any ideas? Here's the closest I've come to getting it to work. I found this idea in this thread: How to add prefix to the files while unzipping in Python? If I could make this work inside my for loop to download and extract the files that would be cool, but it's okay if this happens outside of that loop.
import os
import glob
import pathlib
for file in pathlib.Path(r'C:\Users\UserName\Desktop\Wells').glob("*WaterWells.*"):
dst = f"County_{file}"
os.rename(file, os.path.join(file, dst))
That produces this error:
OSError: [WinError 123] The filename, directory name, or volume label syntax is incorrect: 'C:\\Users\\UserName\\Desktop\\Wells\\Alcona_WaterWells.cpg' -> 'C:\\Users\\UserName\\Desktop\\Wells\\Alcona_WaterWells.cpg\\County_C:\\Users\\UserName\\Desktop\\Wells\\Alcona_WaterWells.cpg'
I'd like to add "County_" to each file. The targeted files use this syntax: CountyName_WaterWells.ext

os.path.basename gets the file name, os.path.dirname gets directory names. Note that these may break if your slashes are in a weird direction. Putting them in your code, it would work like this
import os
import glob
import pathlib
for file in pathlib.Path(r'C:\Users\UserName\Desktop\Wells').glob("*WaterWells.*"):
dst = f"County_{os.path.basename(file)}"
os.rename(file, os.path.join(os.path.dirname(file), dst))

The problem is your renaming variable, dst, adds 'County_' before the entire path, which is given by the file variable.
If you take file and break it up with something like file.split("/") (where you should replace the slash with whatever appears between directories when you print file to terminal) then you should be able to get file broken up as a list, where the final element will be the current filename. Modify just this in the loop, put the whole thing pack together using "".join(_path + modified_dst) and then pass this to os.rename.

Related

How to open a specific path with open()?

I'm trying to build a file transfer system with python3 sockets. I have the connection and sending down but my issue right now is that the file being sent has to be in the same directory as the program, and when you receive the file, it just puts the file into the same directory as the program. How can I get a user to input the location of the file to be sent and select the location of the file to be sent to?
I assume you're opening files with:
open("filename","r")
If you do not provide an absolute path, the open function will always default to a relative path. So, if I wanted to open a file such as /mnt/storage/dnd/5th_edition.txt, I would have to use:
open("/mnt/storage/dnd/4p5_edition","r")
And if I wanted to copy this file to /mnt/storage/trash/ I would have to use the absolute path as well:
open("/mnt/storage/trash/4p5_edition","w")
If instead, I decided to use this:
open("mnt/storage/trash/4p5_edition","w")
Then I would get an IOError if there wasn't a directory named mnt with the directories storage/trash in my present folder. If those folders did exist in my present folder, then it would end up in /whatever/the/path/is/to/my/current/directory/mnt/storage/trash/4p5_edition, rather than /mnt/storage/trash/4p5_edition.
since you said that the file will be placed in the same path where the program is, the following code might work
import os
filename = "name.txt"
f = open(os.path.join(os.path.dirname(__file__),filename))
Its pretty simple just get the path from user
subpath = raw_input("File path = ")
print subpath
file=open(subpath+str(file_name),'w+')
file.write(content)
file.close()
I think thats all you need let me know if you need something else.
like you say, the file should be in the same folder of the project so you have to replace it, or to define a function that return the right file path into your open() function, It's a way that you can use to reduce the time of searching a solution to your problem brother.
It should be something like :
import os
filename = "the_full_path_of_the_fil/name.txt"
f = open(os.path.join(os.path.dirname(__file__),filename))
then you can use the value of the f variable as a path to the directory of where the file is in.

Rename and move file with Python

I have a Python script that compares existing file names in a folder to a reference table and then determines if it needs to be renamed or not.
As it loops through each filename:
'oldname' = the current file name
'newname' = what it needs to be renamed to
I want rename the file and move it to a new folder "..\renamedfiles"
Can I do the rename and the move at the same time as it iterates through the loop?
Yes you can do this. In Python you can use the move function in shutil library to achieve this.
Let's say on Linux, you have a file in /home/user/Downloads folder named "test.txt" and you want to move it to /home/user/Documents and also change the name to "useful_name.txt". You can do both things in the same line of code:
import shutil
shutil.move('/home/user/Downloads/test.txt', '/home/user/Documents/useful_name.txt')
In your case you can do this:
import shutil
shutil.move('oldname', 'renamedfiles/newname')
os.rename (and os.replace) won't work if the source and target locations are on different partitions/drives/devices. If that's the case, you need to use shutil.move, which will use atomic renaming if possible, and fallback to copy-then-delete if the destination is not on the same file system. It's perfectly happy to both move and rename in the same operation; the operation is the same regardless.
To do both of the operations, you can use the os.rename(src, dest) function.
You should have the wanted directory to save the file in, and the new file name. You can do this for every file you run across in your loop.
For example:
# In Windows
dest_dir = "tmp\\2"
new_name = "bar.txt"
current_file_name = "tmp\\1\\foo.txt"
os.rename(current_file_name, os.path.join(dest_dir, new_name))
The rename function allows you to change the name of the file and it's folder at the same time.
To prevent any errors in renaming and moving of the file, use shutil.move.
Since Python 3.4, working with paths is done easily with pathlib. Moving/renaming a file is done with rename or replace (will unconditionally do the replace). So combining with the parent attribute and the concat operator, you can do:
from pathlib import Path
source = Path("path/to/file/oldname")
target = source.replace(source.parent / "renames" / "newname")
Create a Python file in your desired directory and write something like that :
import os
for filename in os.listdir("."):
if(filename ...):
newFilename = ...
os.rename(filename, newFilename)

How to change all file's type to a specific in a folder?

These Files are containing different file-types. after trying bunch file name changing and using such techniques using cmd this didn't changed. find the screenshot for better understanding.
I've used such code of Python from here but it didn't worked.
How to change multiple filenames in a directory using Python
You could use os to rename, and glob to conveniently get the list of files:
import os, glob
def rename(files, pattern, replacement):
for pathname in glob.glob(files):
basename= os.path.basename(pathname)
new_filename= basename.replace(pattern, replacement)
if new_filename != basename:
os.rename(
pathname,
os.path.join(os.path.dirname(pathname), new_filename))
rename('*.XXX', 'XXX', 'YYY')
Inspired in this answer.
I've Tried this code in cmd to change file name.
but it is changing one file-type at once.
ren [Something].XXX [Something].YYY
Even for changing the file-type of Multiple files in a folder
ren *.XXX *.YYY
But I'm trying to get specifically changing multiple file-types to single file-type.
[Some output i've got][1] : https://i.stack.imgur.com/Kdwzx.png

Python - Deleting the last few characters of specific files in a directory

I'm trying to delete the last several characters of multiple files in a specific directory using the rename function. The code I have written using suggestions on this site looks like it should work, but it returns the error message:
FileNotFoundError: [WinError 2] The system cannot find the file specified: 'test1.txt' -> 'test'
And here is my code:
import os
list = os.listdir("C:\\Users\\Jonathan\\Desktop")
for file in list:
if file.startswith("test"):
os.rename(file, file[0:4])
My code shows that for all files beginning with the word "test", delete all characters after it. As I said, to me it looks like it should work, but I am new at Python, and I don't even understand what the error message means.
Are you actually in the folder where you're renaming? If not, the problem is likely that you're looking in the local folder (where you launched the program). Prepend that path to each file name:
import os
cwd = "C:\\Users\\Jonathan\\Desktop"
list = os.listdir(cwd)
for file in list:
if file.startswith("test"):
os.rename(cwd+file, cwd+"test")
As you didn't specify the complete path to your file, it is likely that your program was saving the in your root directory. Also, you should not use list or file as variable names since they shadow two of Python's types.
import os
files_path = "C:\\Users\\Jonathan\\Desktop\\"
lst = os.listdir(files_path)
for file_name in lst:
if file_name.startswith("test"):
os.rename(files_path + file_name, files_path + file_name[:-4])
Try this:
import os
list = os.listdir("C:\\Users\\Jonathan\\Desktop\\")
for file in list:
if file[:4] == "test":
os.renames(list+file, list+file[:4])
And by the way, if you need find the files and rename them recursively(That means will find all directories in that directory). You can use os.walk() like this:
for root, dirs, files in os.walk("C:\\Users\\Jonathan\\Desktop\\"):
for name in files:
if name[:4] == "test":
os.renames(os.path.join(root, name), os.path.join(root, name)[:4])
you need to use os.rename() with existing paths. if your working directory is not the directory containing the file your script will fail. this should work independently of your working directory:
files_path = "C:\\Users\\Jonathan\\Desktop\\"
lst = os.listdir(files_path)
for fle in lst:
if fle.startswith("test"):
os.rename(os.path.join(files_path, fle),
os.path.join(files_path, fle[:4]) )
and avoid using list as a varaible name.

taking data from files which are in folder

How do I get the data from multiple txt files that placed in a specific folder. I started with this could not fix. It gives an error like 'No such file or directory: '.idea' (??)
(Let's say I have an A folder and in that, there are x.txt, y.txt, z.txt and so on. I am trying to get and print the information from all the files x,y,z)
def find_get(folder):
for file in os.listdir(folder):
f = open(file, 'r')
for data in open(file, 'r'):
print data
find_get('filex')
Thanks.
If you just want to print each line:
import glob
import os
def find_get(path):
for f in glob.glob(os.path.join(path,"*.txt")):
with open(os.path.join(path, f)) as data:
for line in data:
print(line)
glob will find only your .txt files in the specified path.
Your error comes from not joining the path to the filename, unless the file was in the same directory you were running the code from python would not be able to find the file without the full path. Another issue is you seem to have a directory .idea which would also give you an error when trying to open it as a file. This also presumes you actually have permissions to read the files in the directory.
If your files were larger I would avoid reading all into memory and/or storing the full content.
First of all make sure you add the folder name to the file name, so you can find the file relative to where the script is executed.
To do so you want to use os.path.join, which as it's name suggests - joins paths. So, using a generator:
def find_get(folder):
for filename in os.listdir(folder):
relative_file_path = os.path.join(folder, filename)
with open(relative_file_path) as f:
# read() gives the entire data from the file
yield f.read()
# this consumes the generator to a list
files_data = list(find_get('filex'))
See what we got in the list that consumed the generator:
print files_data
It may be more convenient to produce tuples which can be used to construct a dict:
def find_get(folder):
for filename in os.listdir(folder):
relative_file_path = os.path.join(folder, filename)
with open(relative_file_path) as f:
# read() gives the entire data from the file
yield (relative_file_path, f.read(), )
# this consumes the generator to a list
files_data = dict(find_get('filex'))
You will now have a mapping from the file's name to it's content.
Also, take a look at the answer by #Padraic Cunningham . He brought up the glob module which is suitable in this case.
The error you're facing is simple: listdir returns filenames, not full pathnames. To turn them into pathnames you can access from your current working directory, you have to join them to the directory path:
for filename in os.listdir(directory):
pathname = os.path.join(directory, filename)
with open(pathname) as f:
# do stuff
So, in your case, there's a file named .idea in the folder directory, but you're trying to open a file named .idea in the current working directory, and there is no such file.
There are at least four other potential problems with your code that you also need to think about and possibly fix after this one:
You don't handle errors. There are many very common reasons you may not be able to open and read a file--it may be a directory, you may not have read access, it may be exclusively locked, it may have been moved since your listdir, etc. And those aren't logic errors in your code or user errors in specifying the wrong directory, they're part of the normal flow of events, so your code should handle them, not just die. Which means you need a try statement.
You don't do anything with the files but print out every line. Basically, this is like running cat folder/* from the shell. Is that what you want? If not, you have to figure out what you want and write the corresponding code.
You open the same file twice in a row, without closing in between. At best this is wasteful, at worst it will mean your code doesn't run on any system where opens are exclusive by default. (Are there such systems? Unless you know the answer to that is "no", you should assume there are.)
You don't close your files. Sure, the garbage collector will get to them eventually--and if you're using CPython and know how it works, you can even prove the maximum number of open file handles that your code can accumulate is fixed and pretty small. But why rely on that? Just use a with statement, or call close.
However, none of those problems are related to your current error. So, while you have to fix them too, don't expect fixing one of them to make the first problem go away.
Full variant:
import os
def find_get(path):
files = {}
for file in os.listdir(path):
if os.path.isfile(os.path.join(path,file)):
with open(os.path.join(path,file), "r") as data:
files[file] = data.read()
return files
print(find_get("filex"))
Output:
{'1.txt': 'dsad', '2.txt': 'fsdfs'}
After the you could generate one file from that content, etc.
Key-thing:
os.listdir return a list of files without full path, so you need to concatenate initial path with fount item to operate.
there could be ideally used dicts :)
os.listdir return files and folders, so you need to check if list item is really file
You should check if the file is actually file and not a folder, since you can't open folders for reading. Also, you can't just open a relative path file, since it is under a folder, so you should get the correct path with os.path.join. Check below:
import os
def find_get(folder):
for file in os.listdir(folder):
if not os.path.isfile(file):
continue # skip other directories
f = open(os.path.join(folder, file), 'r')
for line in f:
print line

Categories