Newish Python guy here. I've written what I thought would be a fairly simple script to extract the creation date metadata from photos and video and move them to a new folder based on year and month. I'm using PIL for picture and hachoir for video metadata.
For the most part I've got it working until I actually use shutil.move. At that point all the jpg's move to the new folders just fine. But all the videos are being COPIED. The original files are being left in the source folder.
My assumption is that some process that I invoke during the script is still accessing the video file and not letting it be deleted. Can anyone tell me what I'm messing up, and how I can release these video files to be moved?
========================
import os.path, time, sys, shutil
from PIL import Image
from PIL.ExifTags import TAGS
from hachoir_core.error import HachoirError
from hachoir_core.cmd_line import unicodeFilename
from hachoir_parser import createParser
from hachoir_core.tools import makePrintable
from hachoir_metadata import extractMetadata
from hachoir_core.i18n import getTerminalCharset
def get_field (exif,field) :
for (k,v) in exif.iteritems():
if TAGS.get(k) == field:
return v
for picture in os.listdir(os.getcwd()):
if picture.endswith(".jpg") or picture.endswith(".JPG"):
print picture
rawMetadata = Image.open(picture)._getexif()
datetime = get_field(rawMetadata, 'DateTime')
datedict = {'year' : datetime[0:4], 'month' : datetime[5:7]}
target = datedict['year']+'-'+ datedict['month']
if not os.path.isdir(target):
newdir = os.mkdir(target)
if picture not in target:
shutil.move(picture, target)
if picture.endswith('.mov') or picture.endswith('.MOV') or \
picture.endswith('mp4') or picture.endswith('.MP4'):
picture, realname = unicodeFilename(picture), picture
parser = createParser(picture, realname)
rawMetadata = extractMetadata(parser)
text = rawMetadata.exportPlaintext()
datedict = {'year' : text[4][17:21], 'month' : text[4][22:24]}
target = datedict['year']+'-'+ datedict['month']
dest = os.path.join(target, picture)
if not os.path.isdir(target):
newdir = os.mkdir(target)
if picture not in target:
try:
shutil.move(picture, dest)
except WindowsError:
pass
The in operator says whether items are in collections (e.g. an element in a list) or strings are substrings of other strings. It doesn't know that your string variable target is the name of a directory, nor does it know anything about checking directories to see if files are in them. Instead, use:
if os.path.exists(dest):
It's hard to tell what exactly is failing without a decent error code. Use this in your except block to get more answers:
except WindowsError as e:
print("There was an error copying {picture} to {target}".format(
picture=picture,target=target))
print("The error thrown was {e}".format
(e=e))
print("{picture} exists? {exist}".format(
picture=picture, exist=os.exists(picture))
print("{target} exists? {exist}".format(
target=target,exist=os.exists(target))
Note that much can be said for the logging module for errors like these. It's rather outside the scope of this question, though.
Related
I was searching today for options to manipulate some log files, after executing actions on them, and I found that Python has the os.rename resource, after importing the os module, but I have some regex doubts..
Tried to fit a wildcard "*****" on my file names, but Python seems not to understand it.
My file names are:
Application_2021-08-06_hostname_[PID].log
Currently I'm asking Python to read these application files, and search for defined words/phrases such as "User has logged in", "User disconnected" and etc. And he does well. I'm using datetime module so Python will always read the current files only.
But what I'm trying to do now, is to change the name of the file, after Python read it and execute something. So when he find "Today's sessions are done", he will change the name of the file to:
Application_06-08-2021_hostname_[PID].log
Because it will be easier for manipulating later..
Considering that [PID] will always change, this is the part that I wanted to set the wildcard, because it can be 56, 142, 3356, 74567 or anything.
Using the os.rename module, I've got some errors. What do you suggest?
Code:
import os
import time
from datetime import datetime
path = '/users/application/logs'
file_name = 'Application_%s_hostname_'% datetime.now().strftime('%Y-%m-%d')
new_file_name = 'Application_%s_hostname_'% datetime.now().strftime('%d-%m-%Y')
os.rename(file_name, new_file_name)
The error is:
OSError: [Errno 2] No such file or directory
You can use glob which allows for wildcards:
import glob, os
from datetime import datetime
current_date = datetime.now()
path = '/users/application/logs'
# note the use of * as wild card
filename ='Application_%s_hostname_*'% current_date.strftime('%Y-%m-%d')
full_path = os.path.join(path, filename)
replace_file = glob.glob(full_path)[0] # will return a list so take first element
# or loop to get all files
new_name = replace_file.replace( current_date.strftime('%Y-%m-%d'), current_date.strftime('%d-%m-%Y') )
os.rename(replace_file, new_name)
I've got a large set of images(in one folder) and I've labeled them using software. The output is a json file which contains the labels. I want to write a script that should be able to create folders and move the images according to the description label on the json file. So far I've got python to access json file and display the required label.
CODE1 :
import json
import os
with open('filedirectory.json') as json_data:
data = json.load(json_data)
for i, r in enumerate(data):
if r['label'] != 'tag'
print(i)
print(r['label']['tag1'])
CODE2 :
import json
import os
import shutil
path = "filedirectory//samplefolder"
try:
os.mkdir(path)
except OSError:
print ("Creation of the directory %s failed" % path)
else:
print ("Successfully created the directory %s " % path)
source = "filedirectory//images"
dest1 = "filedrectory//tag1"
dest1 = "filedrectory//tag2"
files = os.listdir(source)
with open('filedirectory.json') as json_data:
data = json.load(json_data)
for i, r in enumerate(data):
if r['label']['tag1'] = 'tag1'
shutil.move(f, tag1)
The first code displays the label output.
The second code is what I want to try but not sure if it'll work. Any help?
I see following issues with CODE2:
is: if r['label']['tag1'] = 'tag1'
should be: if r['label']['tag1'] == 'tag1'
in line: shutil.move(f, tag1) you are using f and tag1, but tag1 is not defined earlier and f is not defined earlier.
I do not know if there are other problems, but if you are fearing it will make mess with your files I suggest you to create function (at begin of CODE2) as follows:
def mock_move(a,b):
print('moving from:',a,'to',b)
Then replacing shutil.move with mock_move and launching your CODE2, thus you will be able to check if it is doing what it should without any movements of your files. After you are sure it works as intended you might replace mock_move with shutil.move and launch CODE2.
I use GIMP for some batch editing, part of this is exporting painting with the filename taken from original image "filename" with this code:
pdb.file_png_save_defaults(ima, drawable, fullpath, filename)
At this moment, I have
fullpath=filename
so it saves the image into same folder as the source and filename and fullpath are identical.
What I want to do is to put it into subdirectory in this folder, lets call it "subfolder". But if I try:
fullpath = '\subfolder\'+filename
I get an error, obviously, because I am working with Python (or any programming language) for like half an hour and I hardly know what I am doing. Does anybody know how to achieve exporting images into a subfolder?
UPDATE:
Now it looks like this
sourcename = pdb.gimp_image_get_filename(ima)
basedir = os.path.dirname(sourcename)
if os.path.isdir(os.path.join(basedir,'Subfolder')) is False:
os.makedirs(os.path.join(basedir,'Subfolder'))
fullpath = os.path.join(basedir,'Subfolder',filename)
... and it works well. Almost. Now I am facing the problem with diacritics in basedir. When basedir contains something like "C:\Ăšklid\" I get "no such file or directory" error when code is creating Subdirecotry in it. After I rename the source folder to "C:\Uklid\" it works with ease. But I do need it to work with every path valid in Windows OS. Can someone help me with that?
UPDATE 2:
Looks like unicode() did the trick:
sourcename = pdb.gimp_image_get_filename(ima)
basedir = os.path.dirname(sourcename)
if os.path.isdir(os.path.join(basedir,'Subfolder')) is False:
os.makedirs(unicode(os.path.join(basedir,'Subfolder')))
fullpath = os.path.join(basedir,'Subfolder',filename)
Try this out:
import os
sourcename = pdb.gimp_image_get_filename(ima) # gets full name of source file
basedir= os.path.dirname(sourcename) # gets path
name = pdb.gimp_layer_get_name(ima.layers[0]) # gets name of active layer
filename = name+'.png'
fullpath = os.path.join(basedir,'subfolder',filename) # use os.path.join to build paths
# new line vvv
os.makedirs(os.path.join(basedir,'subfolder')) # make directory if it doesn't exist
drawable = pdb.gimp_image_active_drawable(ima)
pdb.file_png_save_defaults(ima, drawable, fullpath, filename) # saves output file
I have a list named source where I store the file names. Now based on the extension of each file I want it to copy to different folders. I know it is a very simple task but somehow i am not getting it. Her is my code:
import shutil , os
source = ['test_sound.wav','ts.raw']
src= '/home/GM/codec_implement/Audio_files'
destination1= '/home/GM/codec_implement/raw_files'
destination2= '/home/GM/codec_implement/raw_files/wave_files'
for files in source:
fileName, fileExtension = os.path.splitext(files)
if (fileExtension=='.raw'):
full_filename = os.path.join(source, files)
shutil.copy(full_filename,destination1)
elif (fileExtension=='.wav'):
full_filename = os.path.join(source, files)
shutil.copy(full_filename,destination2)
else:
print "This is not a valid file format "
Errors: I get errors like unexpected indentation all the time I dont understand where I am making mistake and I am using Python 2.7
You need to move line fileName, fileExtension = os.path.splitext(files) four spaces to the right.
Take a look at the pylint. It will show you where the error is.
for example, running pylint against your code:
pylint -r n /tmp/foo
************* Module foo
E: 13,0: expected an indented block
I'm looking for a way to copy an image file from a given source with Python.
I did read several stuff on the internet but what I found was always working just on one specific platform. I would like to know if there exists a functionality in Python that would make it possible to easily copy an image file ?
My target would be to have this in the end :
folder/image_title.jpg
copying the image
new_folder/new_image_title.jpg
with the *new_image_title* being the date of the day.
My code looks like this at the moment :
import shutil
import datetime
shutil.copy('folder/alpha.jpg', 'new_folder/'datetime.date()'.jpg')
But I get an error: SyntaxError: invalid syntax
Update:
You probably want a simple string for your second argument:
instead of this:
shutil.copy('folder/alpha.jpg', 'new_folder/'datetime.date()'.jpg')
try:
dest = new_folder + '/' + str(datetime.date(2012, 8, 19)) + '.jpg'
shutil.copy('folder/alpha.jpg', dest)
with:
new_folder = 'bla'
dest becomes:
'bla/2012-08-19.jpg'
tweak as needed to make the name unique (add time stamp?). Also note, it's usually better to use os.path.join() for creating new paths.
You are getting a SyntaxError because your string forming syntax is incorrect. Corrected, the code would look like this:
import shutil
import datetime
import os
DATE_FORMAT = '%Y-%m-%d'
filename = 'folder/alpha.jpg'
target_folder = 'new_folder'
ext = os.path.splitext(filename)[1]
shutil.copy(filename,
os.path.join(target_folder, '%s%s'
% (datetime.datetime.now().strftime(DATE_FORMAT), ext))
install exiftool
and run command in the photo path:
exiftool -d "./%Y-%m-%d" "-directory
I'm done with it, thanks to you :)
So here is my final version, in case it could help other people :
import shutil
import datetime
now = datetime.datetime.now()
date=str(now.year)+'-'+str(now.month)+'-'+str(now.day)
new_folder = "source/new_folder"
dest = new_folder + '/' + str(date) + '.jpg'
shutil.copy('source/alpha.jpg', dest)
One last thing : at the moment, the program just runs without saying anything. So does anyone knows how to print a message saying whether or not the copying did work ?