How can i apply a script for file modification in all subfolder (in python)?
I created a little script for rename some pictures but my program only change pictures in the script folder and not in subfolder.
from PIL import Image
from os import *
import sys
from os.path import basename
import os
#from PIL.ExifTags import TAGS
from datetime import datetime
extension = ''
#path='/home/pi/Desktop/testrename'
folder_path = "/home/pi/Desktop/testrename/"
l=[]
import PIL.Image
from os import walk
#from path import path
import glob
EXIF_DATETIME = 36867
def renamefinaljpeg() :
glob.glob ('*/.jpeg')
if len(fname) < 20 :
try :
old = PIL.Image.open(fname)._getexif()[EXIF_DATETIME]
old2 = old.split(' ')
os.rename (fname, "yes" + old2[0]+' '+fname)
print('fait')
except :
pass
print('pas jpeg')
def renamefinaljpg() :
glob.glob ('*/.jpg')
if len(fname) < 20 :
try :
old = PIL.Image.open(fname)._getexif()[EXIF_DATETIME]
old2 = old.split(' ')
os.rename (fname, "yes" + old2[0]+' '+fname)
print('fait')
except :
pass
print('pas jpg')
rootDir = "/home/pi/Desktop/testrename/"
for dirName, subdirlist, fileList in os.walk(rootDir) :
for fname in fileList :
print(fname)
try :
renamefinaljpg() or renamefinaljpeg()
except :
pass
print('passe')
The image are renamed in the main directory but not in directory tree (but they are read)
Thank you for your help.
It looks like you've already got a lot of ideas for how to do it in your script. Let's use os.walk since that's probably the most straightforward. os.walk will iterate over all of our directories recursively and give us the list of filenames contained in each one. To filter the files to only .jpg we can use fnmatch.fnmatch.
import fnmatch
import os
import sys
from PIL import Image
folder_path = '/home/pi/Desktop/testrename/old'
# Give special numbers a specific name so it's easier to remember what it
# actually means.
EXIF_DATETIME = 36867
def renamefinal(dir_path, filename):
try:
old = Image.open(file_path)._getexif()[EXIF_DATETIME]
date, time = old.split(' ', maxsplit=1)
new_filename = date + ' ' + filename
os.rename(
# Source file name, including directory and filename
os.path.join(dir_path, filename),
# Destination file name, including date
os.path.join(dir_path, new_filename))
print(
'jpg renommé ({}): {} to {}'.format(
dir_path, filename, new_filename))
except:
# Including filename in our output so we know what to check if
# something goes wrong.
print('pas jpg ({}): {}'.format(dir_path, filename))
for path, dirs, files in os.walk(folder_path):
for filename in files:
if not fnmatch.fnmatch(filename, '*.jpg'):
# Go to the next file, skipping the rest of the loop for this file.
continue
if 30 <= len(filename):
continue
renamefinal(path, filename)
Some more that might help:
If you want to take arguments to your script check out the argparse module.
Try to catch exceptions more specifically, for example using except KeyError: instead of except: when you know that EXIF_DATETIME may not be in the exif data - also try putting your try: ... except: ... block only around the lines that might actually fail.
Check out the logging module instead of using print to show information about what your script is doing.
Related
The code i am currently working on, enters a directory. Once in that directory I need to iterate through the files in that directory and print the file names and extensions, along with the file size.
os.chdir(Path('pets', 'cats'))
current = Path.cwd()
for file in os.listdir(current):
fileName = os.path.split(file)
fileSize = os.path.getsize(file)
print(str(fileName) + ': ' + str(fileSize))
The issue I am having is that the printout includes ('' '<filename.ext>'). I want to omit all these extra characters and just have <filename.ext>. Any clues on how I can clean this up?
It looks like you're using the pathlib module, so you can write:
import os
from pathlib import Path
path = Path('dogs', 'cats')
for item in path.iterdir():
if not item.is_file():
continue
fstat = os.stat(item)
print(f'{item.name}: {fstat.st_size}')
This would yield output like:
foo.txt: 32
bar.txt: 64
You could use this piece of code for the task:
import glob
import os
folPath = r'dir_address'
for fPath in glob.glob("{0}\**\*".format(folPath), recursive=True):
# get file size
fSize = os.stat(fPath).st_size/1024
print('size of {0} is {1}'.format(fPath, fSize))
I hope this helps you.
I would like to change the extension of the files in specific folder. i read about this topic in the forum. using does ideas, I have written following code and I expect that it would work but it does not. I would be thankful for any guidance to find my mistake.
import os,sys
folder = 'E:/.../1936342-G/test'
for filename in os.listdir(folder):
infilename = os.path.join(folder,filename)
if not os.path.isfile(infilename): continue
oldbase = os.path.splitext(filename)
infile= open(infilename, 'r')
newname = infilename.replace('.grf', '.las')
output = os.rename(infilename, newname)
outfile = open(output,'w')
The open on the source file is unnecessary, since os.rename only needs the source and destination paths to get the job done. Moreover, os.rename always returns None, so it doesn't make sense to call open on its return value.
import os
import sys
folder = 'E:/.../1936342-G/test'
for filename in os.listdir(folder):
infilename = os.path.join(folder,filename)
if not os.path.isfile(infilename): continue
oldbase = os.path.splitext(filename)
newname = infilename.replace('.grf', '.las')
output = os.rename(infilename, newname)
I simply removed the two open. Check if this works for you.
You don't need to open the files to rename them, os.rename only needs their paths. Also consider using the glob module:
import glob, os
for filename in glob.iglob(os.path.join(folder, '*.grf')):
os.rename(filename, filename[:-4] + '.las')
Something like this will rename all files in the executing directory that end in .txt to .text
import os, sys
for filename in os.listdir(os.path.dirname(os.path.abspath(__file__))):
base_file, ext = os.path.splitext(filename)
if ext == ".txt":
os.rename(filename, base_file + ".text")
import os
dir =("C:\\Users\\jmathpal\\Desktop\\Jupyter\\Arista")
for i in os.listdir(dir):
files = os.path.join(dir,i)
split= os.path.splitext(files)
if split[1]=='.txt':
os.rename(files,split[0]+'.csv')
#!/usr/bin/env python
'''
Batch renames file's extension in a given directory
'''
import os
import sys
from os.path import join
from os.path import splitext
def main():
try:
work_dir, old_ext, new_ext = sys.argv[1:]
except ValueError:
sys.exit("Usage: {} directory old-ext new-ext".format(__file__))
for filename in os.listdir(work_dir):
if old_ext == splitext(filename)[1]:
newfile = filename.replace(old_ext, new_ext)
os.rename(join(work_dir, filename), join(work_dir, newfile))
if __name__ == '__main__':
main()
If you have python 3.4 or later, you can use pathlib. It is as follows. This example is for changing .txt to .md.
from pathlib import Path
path = Path('./dir')
for f in path.iterdir():
if f.is_file() and f.suffix in ['.txt']:
f.rename(f.with_suffix('.md'))
With print and validation.
import os
from os import walk
mypath = r"C:\Users\you\Desktop\test"
suffix = ".png"
replace_suffix = ".jpg"
filenames = next(walk(mypath), (None, None, []))[2]
for filename in filenames:
if suffix in filename:
print(filename)
rep = input('Press y to valid rename : ')
if rep == "y":
for filename in filenames:
if suffix in filename:
os.rename(mypath+"\\"+filename, mypath+"\\"+filename.replace(suffix, replace_suffix))
I am new to Python coding so here a question. I want to find files that are called "untitled" with any kind of extension, e.g. jpg, indd, psd. Then rename them to the date of the current day.
I have tried the following:
import os
for file in os.listdir("/Users/shirin/Desktop/Artez"):
if file.endswith("untitled.*"):
print(file)
When I run the script, nothing happens.
You might find the glob function more useful in this situation:
import glob
for file in glob.glob("/Users/shirin/Desktop/Artez/untitled.*"):
print(file)
Your function does not print anything as there are probably no files ending with .* in the name. The glob.glob() function will carry out the file expansion for you.
You can then use this to do your file renaming as follows:
import glob
import os
from datetime import datetime
current_day = datetime.now().strftime("%Y-%m-%d")
for source_name in glob.glob("/Users/shirin/Desktop/Artez/untitled.*"):
path, fullname = os.path.split(source_name)
basename, ext = os.path.splitext(fullname)
target_name = os.path.join(path, '{}{}'.format(current_day, ext))
os.rename(source_name, target_name)
A Python datetime object can be used to get you a suitable timestamp.
Python string comparator does not support wildcards. You can search for "untitled." anywhere in the text:
import os
for file in os.listdir("/Users/shirin/Desktop/Artez"):
if "untitled." in file:
print(file)
keep in mind that this will include any file that has "untitled." at any location of the file.
try with this approach
import os
directoryPath = '/Users/shirin/Desktop/Artez'
lstDir = os.walk(directoryPath)
for root, dirs, files in lstDir:
for fichero in files:
(filename, extension) = os.path.splitext(fichero)
if filename.find('untitle') != -1: # == 0 if starting with untitle
os.system('mv '+directoryPath+filename+extension+' '+directoryPath+'$(date +"%Y_%m_%d")'+filename+extension)
import os
for file in os.listdir("/Users/shirin/Desktop/Artez"):
if(file.startswith("untitled")):
os.rename(file, datetime.date.today().strftime("%B %d, %Y") + "." + file.split(".")[-1])
I would like to change the extension of the files in specific folder. i read about this topic in the forum. using does ideas, I have written following code and I expect that it would work but it does not. I would be thankful for any guidance to find my mistake.
import os,sys
folder = 'E:/.../1936342-G/test'
for filename in os.listdir(folder):
infilename = os.path.join(folder,filename)
if not os.path.isfile(infilename): continue
oldbase = os.path.splitext(filename)
infile= open(infilename, 'r')
newname = infilename.replace('.grf', '.las')
output = os.rename(infilename, newname)
outfile = open(output,'w')
The open on the source file is unnecessary, since os.rename only needs the source and destination paths to get the job done. Moreover, os.rename always returns None, so it doesn't make sense to call open on its return value.
import os
import sys
folder = 'E:/.../1936342-G/test'
for filename in os.listdir(folder):
infilename = os.path.join(folder,filename)
if not os.path.isfile(infilename): continue
oldbase = os.path.splitext(filename)
newname = infilename.replace('.grf', '.las')
output = os.rename(infilename, newname)
I simply removed the two open. Check if this works for you.
You don't need to open the files to rename them, os.rename only needs their paths. Also consider using the glob module:
import glob, os
for filename in glob.iglob(os.path.join(folder, '*.grf')):
os.rename(filename, filename[:-4] + '.las')
Something like this will rename all files in the executing directory that end in .txt to .text
import os, sys
for filename in os.listdir(os.path.dirname(os.path.abspath(__file__))):
base_file, ext = os.path.splitext(filename)
if ext == ".txt":
os.rename(filename, base_file + ".text")
import os
dir =("C:\\Users\\jmathpal\\Desktop\\Jupyter\\Arista")
for i in os.listdir(dir):
files = os.path.join(dir,i)
split= os.path.splitext(files)
if split[1]=='.txt':
os.rename(files,split[0]+'.csv')
#!/usr/bin/env python
'''
Batch renames file's extension in a given directory
'''
import os
import sys
from os.path import join
from os.path import splitext
def main():
try:
work_dir, old_ext, new_ext = sys.argv[1:]
except ValueError:
sys.exit("Usage: {} directory old-ext new-ext".format(__file__))
for filename in os.listdir(work_dir):
if old_ext == splitext(filename)[1]:
newfile = filename.replace(old_ext, new_ext)
os.rename(join(work_dir, filename), join(work_dir, newfile))
if __name__ == '__main__':
main()
If you have python 3.4 or later, you can use pathlib. It is as follows. This example is for changing .txt to .md.
from pathlib import Path
path = Path('./dir')
for f in path.iterdir():
if f.is_file() and f.suffix in ['.txt']:
f.rename(f.with_suffix('.md'))
With print and validation.
import os
from os import walk
mypath = r"C:\Users\you\Desktop\test"
suffix = ".png"
replace_suffix = ".jpg"
filenames = next(walk(mypath), (None, None, []))[2]
for filename in filenames:
if suffix in filename:
print(filename)
rep = input('Press y to valid rename : ')
if rep == "y":
for filename in filenames:
if suffix in filename:
os.rename(mypath+"\\"+filename, mypath+"\\"+filename.replace(suffix, replace_suffix))
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.***