I want to rename some of my files using python.
The script should sort all files using date and add 1,2,3,... before actual file names.
Actual file name should not be changed.
Try this:
from os import listdir, rename
from os.path import getmtime
path = 'your_path'
filesName = listdir(path)
filesName.sort(key=lambda fileName: getmtime(path + fileName))
i=1
for fileName in filesName:
rename(path + fileName, path + str(i) + fileName)
i +=1
Every day I am running my script which outputs a log file. I have an external Hive table reading all files in the folder not having the prefix "_". Therefore, whenever I am running my script I would need to prepend "_" to all files in the folder which end with ".log" and do not have the "_" prefix already.
My folder structure is like this.
-output
-_data-2020-04-10.log
-data-2020-04-11.log
And my code is currently like this
if __name__ == "__main__"
df = fetch_todays_data() #Returns dataframe
if not [f for f in os.listdir(dataPath) if not f.startswith('_') and f.endswith(".log")] == []:
fileset = [f for f in os.listdir(dataPath) if not f.startswith('_') and f.endswith(".log")]
for f in fileset:
#### prepend "_" to all files.
dataframe_to_json_log(output_path+/'data-{}'.format(datetime.date.today())) #Help function that transforms dataframe to json_blob in output folder
How do I correctly prepend "_" to all files in fileset?
EDIT:
I did not know the meaning of append, it should be prepend.
Similar to what TheMechanist has but without affecting files that already have the "_" prefix :
import glob, os
fileset = [f for f in glob.glob("*.log") if not f.startswith('_')]
for f in fileset:
os.rename(f, "_" + f)
You can use glob :
from os.path import basename
import glob, os
path = 'mypath'
os.chdir(path)
basename(path)
for file in glob.glob("*.log"):
os.rename(basename, "_"+basename)
excerpt from my python script located at C:\Users\my_name\documents\python_projects\randomness\random.py :
some_number = 3452342
filename = str(some_number) + '.csv'
# file 3452342.csv is stored in C:\Users\my_name\documents\python_projects\randomness\history
# call a function that takes the filename as the parameter
my_func(r'history\filename')
It triggers the following error:
FileNotFoundError: [Errno 2] File b'history\filename' does not exist: b'history\filename'
what exactly is going wrong here?
How can I pass the filename to my_func when it is located in a sub-folder?
thanks in advance
The answer to your question what's going wrong:
Python tried to open the file with the name literally "filename" in the subdirectory named "history", which is doesn't exist. You should pass the filename variable's value instead as follows:
You should use os.path.join().
import os
some_number = 3452342
filename = str(some_number) + '.csv'
workdir = "C:\Users\my_name\documents\python_projects\randomness\history"
my_func(os.path.join(workdir, filename))
Or if the file 3452342.csv placed in a subfolder (called history) of the the main script's directory, then you can use:
import os
some_number = 3452342
filename = str(some_number) + '.csv'
my_func(os.path.join("history", filename))
Alternatively you can simply use string concatenation:
import os
some_number = 3452342
filename = str(some_number) + '.csv'
my_func("history/" + filename)
Another approach using Python's format():
import os
some_number = 3452342
filename = str(some_number) + '.csv'
my_func("history/{}".format(filename))
First try to get the current path then join the path you got with the name of your file.
import os
some_number = 3452342
filename = str(some_number) + '.csv'
path_file = os.path.join(os.getcwd(), filename)
my_func(path_file)
for more about how to work with path using python check out this.
Common pathname manipulations
First, to be platform independent you should use os.path.join to concatenate directories.
Second, like #k88 pointed out, you need to pass the variable filename into your path, not the string 'filename'
The clean way would be:
import os
some_number = 3452342
filename = str(some_number) + '.csv'
# file 3452342.csv is stored in C:\Users\my_name\documents\python_projects\randomness\history
# call a function that takes the filename as the parameter
my_func(os.path.join('history', filename))
Relative Or Absolute Path?
If your history subfolder is a fixed subfolder of your script's directory, you should even consider to determine your target filename as an absolute path like this (see also this answer with comments):
base_dir = os.path.dirname(os.path.abspath(__file__))
my_func(os.path.join(base_dir, 'history', filename))
i have a folder with a lot of files like that:
2012-05-09.txt
2012-05-10.txt
2012-05-11.txt
etc.
now i wanna delete the hyphen and add " _PHOTOS_LOG " that it looks in the end like this:
20120509_PHOTOS_LOG.txt
20120510_PHOTOS_LOG.txt
20120511_PHOTOS_LOG.txt
etc.
How to do ?
thats the code now:
//updated the code, now its working
import os
import glob
import os.path
import sys
src = 'D:\\testing/hyphen1'
src = r'D:\testing\test'
for fn in os.listdir(src):
new_filename = fn.replace('-','').replace('.txt', '_PHOTOS_LOG.txt')
fn = os.path.join(src, fn)
new_filename = os.path.join(src, new_filename)
try:
os.rename(fn, new_filename)
except (WindowsError, OSError):
print 'Error renaming "%s" to "%s"' % (fn, new_filename)
print sys.exc_info()[1]
You could do the rename something like this:
import os
for filename in os.listdir("."):
if filename.endswith(".txt"):
newFilename = filename.replace("-", "")
os.rename(filename, newFilename[:7]+"_PHOTO_LOG.txt")
os.listdir(".") returns the names of the entries in the current folder
filename.endswith(".txt") verifies if the filename is one of your text files
if it is, it removes the - and adds the _PHOTO_LOG at the end
new_filename = old_filename.replace("-", "").replace(".txt", "_PHOTOS_LOG.txt")
That will get you the new filename, if you want to rename all the files, then:
import os
for old_filename in os.listdir("."):
new_filename = old_filename.replace("-", "").replace(".txt", "_PHOTOS_LOG.txt")
os.rename(old_filename, new_filename)
For all of your files in your current directory:
import os
for fn in os.listdir('.'):
new_filename = fn.replace('-','').replace('.txt', '_PHOTOS_LOG.txt')
os.rename(fn, new_filename)
Using os.rename() to change the filenames.
The individual file names will end up a series of strings, so while you usually would want to use methods from the os module, you can simply treat these as strings since you are not looking at paths, but simple filenames and use replace() to create the new names.
--
Example for one filename to show transformation:
fn ='2012-05-09.txt'
then
fn.replace('-','').replace('.txt', '_PHOTOS_LOG.txt')
will yield '20120509_PHOTOS_LOG.txt'
You need to iterate through the list of files
and rename them according to your needs:
import os
import glob
for name in glob.glob('*.txt'):
newname = "%s_PHOTOS_LOG.txt" % name.replace('-','')[:-4]
os.rename(name, newname)
The glob.glob function produces a list of .txt files in the current directory.
I'm trying to rename some files in a directory using Python.
Say I have a file called CHEESE_CHEESE_TYPE.*** and want to remove CHEESE_ so my resulting filename would be CHEESE_TYPE
I'm trying to use the os.path.split but it's not working properly. I have also considered using string manipulations, but have not been successful with that either.
Use os.rename(src, dst) to rename or move a file or a directory.
$ ls
cheese_cheese_type.bar cheese_cheese_type.foo
$ python
>>> import os
>>> for filename in os.listdir("."):
... if filename.startswith("cheese_"):
... os.rename(filename, filename[7:])
...
>>>
$ ls
cheese_type.bar cheese_type.foo
Here's a script based on your newest comment.
#!/usr/bin/env python
from os import rename, listdir
badprefix = "cheese_"
fnames = listdir('.')
for fname in fnames:
if fname.startswith(badprefix*2):
rename(fname, fname.replace(badprefix, '', 1))
The following code should work. It takes every filename in the current directory, if the filename contains the pattern CHEESE_CHEESE_ then it is renamed. If not nothing is done to the filename.
import os
for fileName in os.listdir("."):
os.rename(fileName, fileName.replace("CHEESE_CHEESE_", "CHEESE_"))
Assuming you are already in the directory, and that the "first 8 characters" from your comment hold true always. (Although "CHEESE_" is 7 characters... ? If so, change the 8 below to 7)
from glob import glob
from os import rename
for fname in glob('*.prj'):
rename(fname, fname[8:])
I have the same issue, where I want to replace the white space in any pdf file to a dash -.
But the files were in multiple sub-directories. So, I had to use os.walk().
In your case for multiple sub-directories, it could be something like this:
import os
for dpath, dnames, fnames in os.walk('/path/to/directory'):
for f in fnames:
os.chdir(dpath)
if f.startswith('cheese_'):
os.rename(f, f.replace('cheese_', ''))
Try this:
import os
import shutil
for file in os.listdir(dirpath):
newfile = os.path.join(dirpath, file.split("_",1)[1])
shutil.move(os.path.join(dirpath,file),newfile)
I'm assuming you don't want to remove the file extension, but you can just do the same split with periods.
This sort of stuff is perfectly fitted for IPython, which has shell integration.
In [1] files = !ls
In [2] for f in files:
newname = process_filename(f)
mv $f $newname
Note: to store this in a script, use the .ipy extension, and prefix all shell commands with !.
See also: http://ipython.org/ipython-doc/stable/interactive/shell.html
Here is a more general solution:
This code can be used to remove any particular character or set of characters recursively from all filenames within a directory and replace them with any other character, set of characters or no character.
import os
paths = (os.path.join(root, filename)
for root, _, filenames in os.walk('C:\FolderName')
for filename in filenames)
for path in paths:
# the '#' in the example below will be replaced by the '-' in the filenames in the directory
newname = path.replace('#', '-')
if newname != path:
os.rename(path, newname)
It seems that your problem is more in determining the new file name rather than the rename itself (for which you could use the os.rename method).
It is not clear from your question what the pattern is that you want to be renaming. There is nothing wrong with string manipulation. A regular expression may be what you need here.
import os
import string
def rename_files():
#List all files in the directory
file_list = os.listdir("/Users/tedfuller/Desktop/prank/")
print(file_list)
#Change current working directory and print out it's location
working_location = os.chdir("/Users/tedfuller/Desktop/prank/")
working_location = os.getcwd()
print(working_location)
#Rename all the files in that directory
for file_name in file_list:
os.rename(file_name, file_name.translate(str.maketrans("","",string.digits)))
rename_files()
This command will remove the initial "CHEESE_" string from all the files in the current directory, using renamer:
$ renamer --find "/^CHEESE_/" *
I was originally looking for some GUI which would allow renaming using regular expressions and which had a preview of the result before applying changes.
On Linux I have successfully used krename, on Windows Total Commander does renaming with regexes, but I found no decent free equivalent for OSX, so I ended up writing a python script which works recursively and by default only prints the new file names without making any changes. Add the '-w' switch to actually modify the file names.
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import fnmatch
import sys
import shutil
import re
def usage():
print """
Usage:
%s <work_dir> <search_regex> <replace_regex> [-w|--write]
By default no changes are made, add '-w' or '--write' as last arg to actually rename files
after you have previewed the result.
""" % (os.path.basename(sys.argv[0]))
def rename_files(directory, search_pattern, replace_pattern, write_changes=False):
pattern_old = re.compile(search_pattern)
for path, dirs, files in os.walk(os.path.abspath(directory)):
for filename in fnmatch.filter(files, "*.*"):
if pattern_old.findall(filename):
new_name = pattern_old.sub(replace_pattern, filename)
filepath_old = os.path.join(path, filename)
filepath_new = os.path.join(path, new_name)
if not filepath_new:
print 'Replacement regex {} returns empty value! Skipping'.format(replace_pattern)
continue
print new_name
if write_changes:
shutil.move(filepath_old, filepath_new)
else:
print 'Name [{}] does not match search regex [{}]'.format(filename, search_pattern)
if __name__ == '__main__':
if len(sys.argv) < 4:
usage()
sys.exit(-1)
work_dir = sys.argv[1]
search_regex = sys.argv[2]
replace_regex = sys.argv[3]
write_changes = (len(sys.argv) > 4) and sys.argv[4].lower() in ['--write', '-w']
rename_files(work_dir, search_regex, replace_regex, write_changes)
Example use case
I want to flip parts of a file name in the following manner, i.e. move the bit m7-08 to the beginning of the file name:
# Before:
Summary-building-mobile-apps-ionic-framework-angularjs-m7-08.mp4
# After:
m7-08_Summary-building-mobile-apps-ionic-framework-angularjs.mp4
This will perform a dry run, and print the new file names without actually renaming any files:
rename_files_regex.py . "([^\.]+?)-(m\\d+-\\d+)" "\\2_\\1"
This will do the actual renaming (you can use either -w or --write):
rename_files_regex.py . "([^\.]+?)-(m\\d+-\\d+)" "\\2_\\1" --write
You can use os.system function for simplicity and to invoke bash to accomplish the task:
import os
os.system('mv old_filename new_filename')
This works for me.
import os
for afile in os.listdir('.'):
filename, file_extension = os.path.splitext(afile)
if not file_extension == '.xyz':
os.rename(afile, filename + '.abc')
What about this :
import re
p = re.compile(r'_')
p.split(filename, 1) #where filename is CHEESE_CHEESE_TYPE.***