-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add --fix-file-extension to export #382
Comments
Should there be an option to do this only for original images or only for edited images? The problem can happen on import (originals) or more often on edit but a lot easier to just apply the fix to all images. The would be good with a cache for exiftool #325 |
For this to work with with --download-missing and --use-photos-export, the check will need to occur after the file is exported to the export directory. This could result in the file having a different name which would then make the --update logic think the file was missing resulting in the file being re-downloaded. To avoid this, the following may work:
|
I love this idea! I am running into this issue now, and I am trying to figure out a way to fix the file extensions before running an export, so that everything goes smoothly. |
@PetrochukM how many photos do you have with this problem? Are you intending to do a 1-time export or a recurring export with If you save the following as
it should rename the files with incorrect extension. It doesn't check for name collisions and there may some extensions where there's more than one valid extension (for example, .jpg, .jpeg) in which case """ Example function for use with osxphotos export --post-function option """
import pathlib
from typing import Callable
from osxphotos import ExportResults, PhotoInfo
from osxphotos.exiftool import ExifTool
def fix_extension(
photo: PhotoInfo, results: ExportResults, verbose: Callable, **kwargs
):
"""Call this with osxphotos export /path/to/export --post-function fix_export_extension.py::fix_extension
This will get called immediately after the photo has been exported
See full example here: https://github.com/RhetTbull/osxphotos/blob/master/examples/post_function.py
Args:
photo: PhotoInfo instance for the photo that's just been exported
results: ExportResults instance with information about the files associated with the exported photo
verbose: A function to print verbose output if --verbose is set; if --verbose is not set, acts as a no-op (nothing gets printed)
**kwargs: reserved for future use; recommend you include **kwargs so your function still works if additional arguments are added in future versions
Notes:
Use verbose(str) instead of print if you want your function to conditionally output text depending on --verbose flag
Any string printed with verbose that contains "warning" or "error" (case-insensitive) will be printed with the appropriate warning or error color
Will not be called if --dry-run flag is enabled
Will be called immediately after export and before any --post-command commands are executed
"""
for filepath in results.exported:
filepath = pathlib.Path(filepath)
ext = filepath.suffix.lower()
if not ext:
continue
ext = ext[1:] # remove leading dot
exiftool = ExifTool(filepath)
actual_ext = exiftool.asdict().get("File:FileTypeExtension").lower()
if ext != actual_ext and (ext not in ("jpg", "jpeg") or actual_ext != "jpg"):
# WARNING: Does not check for name collisions; left as an exercise for the reader
verbose(f"Fixing extension for {filepath} from {ext} to {actual_ext}")
new_filepath = filepath.with_suffix(f".{actual_ext}")
verbose(f"Renaming {filepath} to {new_filepath}")
filepath.rename(new_filepath) |
I have 30k photos or so and had a couple of hundred issues. I had several issues with NEF, PNG, and JPEG files. I have been collecting my photos from across the internet, so I intend on doing reoccurring exports as I collect more photos! I have been manually fixing these issues, downloading the images, renaming them, and uploading them. These issues have been coming up regularly, especially with Facebook exports and some iPhone screenshots. Unfortunately, Apple Photos sometimes bugs or crashes when dealing with these types of files. That has made it more challenging to resolve this issue. Today, I needed to find the original files because I could not export the original files from Apple Photos without crashing. Thanks for providing the script, I'll try it out! If I use it with |
Hi @PetrochukM What I do is to try and fix as many problems (extension, EXIF date times, quick time date times, conversions/rotate videos) prior to uploading them to Photos so that osxphotos can then apply it's magic.
PLEASE NOTE MOST OF THESE COMMANDS USE THE -overwrite_original_in_place WHICH WRITES OVER THE FILE ITSELF. SO DO TEST IT OUT AND SAVE COPIES OF THE ORIGINALS, just in case!!!
###############################################################################
#
# EXIFTOOL related commands
#
###############################################################################
#==============================================================================
# exif() Displays some key EXIF tags from files/directories recursively.
#------------------------------------------------------------------------------
function exif() {
# To overcome incompatibility of xattr (loaded by osxphotos).
# Force PATH to force xattr to be sourced from /usr/bin
# *** Adapt/change the location of the txt file
PATH=/usr/bin:$PATH exiftool -r -d """%Y:%m:%d %H:%M:%S""" -p """/Users/YourUser/format.txt""" -f "$@"
}
export -f exif
#------------------------------------------------------------------------------
#==============================================================================
# exiforiginaldate() Copies the original date from EXIF to all other dates in the file. To align all.
#------------------------------------------------------------------------------
function exiforiginaldate () {
echo Performing... """-CreateDate\<DateTimeOriginal""" """-FileModifyDate\<DateOriginalDate"""
# 2017.04.13 Included changing the ModifyDate tag (operating system level, which could also be set via touch command)
exiftool -d """%Y:%m:%d %H:%M:%S""" -overwrite_original_in_place -fileOrder DateTimeOriginal """-CreateDate<DateTimeOriginal""" """-FileModifyDate<DateTimeOriginal""" """-ModifyDate<DateTimeOriginal""" -v "$@"
}
export -f exiforiginaldate
#------------------------------------------------------------------------------
#==============================================================================
# exifKeysdate() Copies Keys:Creation date into OriginalDate. Some videos (QT) have this as the correct date and don't have OriginalDate and/or FileModify sate is wrong.
#------------------------------------------------------------------------------
function exifKeysdate () {
echo Performing... ""-DateTimeOriginal\<Keys:CreationDate""
exiftool -overwrite_original_in_place """-DateTimeOriginal<Keys:CreationDate""" -P -v "$@"
}
export -f exifKeysdate
#------------------------------------------------------------------------------
#==============================================================================
# exifpng2jpg() # Command which convert .PNG files into .JPG and copies EXIF fields ...
#------------------------------------------------------------------------------
function exifpng2jpg() {
# Command which convert .PNG files into .JPG and copies EXIF fields ...
for a in "$@"
do
fname=`basename "$a" .png`
xtension=png
echo 1st - ${fname}.${xtension}
if [ \( -f "${fname}".png -o -f "${fname}".PNG \) -a ! -f "${fname}".jpg ]
then
echo ok - ${fname}.${xtension}
sips -s format jpeg -s formatOptions 90 """${fname}".${xtension}"" --out """${fname}".jpg""
exiftool -overwrite_original_in_place -TagsFromFile "${fname}".${xtension} "-all:all>all:all" "${fname}".jpg
else
fname=`basename "$a" .PNG`
xtension=PNG
echo 2nd - ${fname}.${xtension}
if [ \( -f "${fname}".png -o -f "${fname}".PNG \) -a ! -f "${fname}".jpg ]
then
echo ok - ${fname}.${xtension}
sips -s format jpeg -s formatOptions 90 """${fname}".${xtension}"" --out """${fname}".jpg""
exiftool -overwrite_original_in_place -TagsFromFile "${fname}".${xtension} "-all:all>all:all" "${fname}".jpg
fi
fi
done
}
export -f exifpng2jpg
#------------------------------------------------------------------------------
#==============================================================================
# exiftif2jpg() # Command which convert .TIF files into .JPG and copies EXIF fields ... Uses ModifyDate as the source for DateTimeOriginal, FileModifyDate, CreateDate fields
#------------------------------------------------------------------------------
function exiftif2jpg() {
# Command which convert .TIF files into .JPG and copies EXIF fields ... Uses ModifyDate as the source for DateTimeOriginal, FileModifyDate, CreateDate fields
for a in "$@"
do
fname=`basename "$a" .tif`
dname=`dirname "$a" `
if [ -f "${dname}/${fname}".tif -a ! -f "${dname}/${fname}".jpg ]
then
echo ok - ${fname}
sips -s format jpeg -s formatOptions 100 """${dname}/${fname}".tif"" --out """${dname}/${fname}".jpg""
exiftool -overwrite_original_in_place -TagsFromFile "${dname}/${fname}".tif "-all:all>all:all" "${dname}/${fname}".jpg
# WHy am I using ModifyDate and referencing FileModifyDate?
echo Performing... ""-DateTimeOriginal\<FileModifyDate"" ""-CreateDate\<FileModifyDate"" on "${dname}/${fname}".jpg
exiftool -overwrite_original_in_place """-DateTimeOriginal<ModifyDate""" """-CreateDate<ModifyDate""" """-FileModifyDate<ModifyDate""" -P -v "${dname}/${fname}".jpg
fi
done
}
export -f exiftif2jpg
#------------------------------------------------------------------------------
#==============================================================================
# exifsetdate()Takes a parameters in the format %Y:%m:%d %H:%M:%S and adjust the Original date of file.
#------------------------------------------------------------------------------
function exifsetdate() {
datetoset=${1}; echo $datetoset
shift
exiftool -d """%Y:%m:%d %H:%M:%S""" -overwrite_original_in_place -fileOrder DateTimeOriginal -DateTimeOriginal="""${datetoset}""" -v "$@"
}
export -f exifsetdate
#------------------------------------------------------------------------------
#==============================================================================
# exifsetdate()Takes a parameters in the format %Y:%m:%d %H:%M:%S and adjust the ALL dates of file.
#------------------------------------------------------------------------------
function exifsetalldates() {
datetoset=${1}; echo $datetoset
shift
exiftool -d """%Y:%m:%d %H:%M:%S""" -overwrite_original_in_place -fileOrder DateTimeOriginal -DateTimeOriginal="""${datetoset}""" -CreateDate="""${datetoset}""" -FileModifyDate="""${datetoset}""" -ModifyDate="""${datetoset}""" -v "$@"
}
export -f exifsetalldates
#------------------------------------------------------------------------------
#==============================================================================
# exifrenamefile() Rename the file based on it's Original date. File name format will be: IMG_%Y%m%d_%H%M%S%%-c.%%e and keeping the same extension.
#------------------------------------------------------------------------------
function exifrenamefile() {
#exiftool -v4 -r -d """%Y-%m-%d %H.%M.%S%%-c.%%le""" '-filename<DateTimeOriginal' -f "$@"
# %%le lowers the case of extension. Hopefully %%e keeps the same extension
exiftool -v4 -r -d """IMG_%Y%m%d_%H%M%S%%-c.%%e""" '-filename<DateTimeOriginal' -f "$@"
echo "Note: Do you need to run exiforiginaldate?"
}
export -f exifrenamefile
#------------------------------------------------------------------------------
#==============================================================================
# exifcopytags()
# - srcfile
# - dstfile
# Copy all metadata from one file to another
# exiftool -TagsFromFile srcimage.jpg "-all:all>all:all" targetimage.jpg
# USE -overwrite_original_in_place in applicable
# USE WITHOUT all:all will copy everything including GPS data (works with MP4)
#------------------------------------------------------------------------------
function exifcopytags() {
E_BADARGS=85
E_BADFILES=90
if [ ! -n "$1" -o ! -n "$2" ]
then
echo "Usage: exifcopytags srcfile dstfile"
return $E_BADARGS
elif [ -f "$1" ]
then
srcfile=${1}; shift
echo Copying all tags from "${srcfile}" to "$@"
exiftool -v -overwrite_original_in_place -TagsFromFile "${srcfile}" "${@}"
else
echo "Usage: file(s) not found!"
echo "Usage: exifcopytags srcfile dstfile"
return $E_BADFILES
fi
}
export -f exifcopytags
#------------------------------------------------------------------------------
#==============================================================================
# exifcleantags()
# - files
# Claen all metadata from one file
# exiftool -overwrite_original -all= -gps:all= *.jpg
# USE -overwrite_original_in_place in applicable
#------------------------------------------------------------------------------
function exifcleantags() {
E_BADARGS=85
E_BADFILES=90
if [ ! -n "$1" ]
then
echo "Usage: exifcleantags files"
return $E_BADARGS
elif [ -f "$1" ]
then
echo Cleaning all tags from "$@"
exiftool -v -overwrite_original -all= -gps:all= "${@}"
else
echo "Usage: file(s) not found!"
echo "Usage: exifcleantags files"
return $E_BADFILES
fi
}
export -f exifcleantags
#------------------------------------------------------------------------------ |
Thanks for sending that. I am not sure I am ready to copy all my photos and run that over them. I think it's small enough that I don't want to take that risk (: That said, I did learn from this that EXIF might be hiding metadata that could be useful to me! I have many mystery files that I am struggling to pin down the creation date for. |
@PetrochukM I've added a script find_bad_extensions.py to the examples directory. This will scan your Photos library to find all photos that have a bad extension. It caches the results so when you re-run it, it doesn't have to scan each photo again. If you save the file at the link above to
You can use this to find all the bad extensions then you can export those, fix the extension and re-import them if desired. I intend to eventually add this as an osxphotos command to automatically fix the extensions by automating the export, fix, re-import (and re-apply metadata). Ref. #336 |
You might want to check out |
Thank you so much for this! This should be really helpful! |
See #336 and #381
Photos and external editing apps can apply the incorrect extension. Photos doesn't complain. It's also possible to import a photo with incorrect extension and Photos displays it fine but gets the UTI wrong. It would be good to have an option to fix the extension on export. I think the most reliable way to do this is use exiftool to get the filetype (see comments on #381).
The text was updated successfully, but these errors were encountered: