Rename Files Without Extension

I have an issue where I have recovered from a disk failure and now my image files have no extension. I would like to know how to rename the files with the correct extensions.


the last time I had this issue, I think it was @vikingOSX last time wrote a script... however the script does not run.


can anyone help...


Regards, Paul

Posted on May 21, 2020 11:23 AM

Reply
Question marked as Top-ranking reply

Posted on May 22, 2020 7:33 AM

Hi Paul,


The original post is here — for image validation on files with extensions.


The original script that I wrote last Fall was used to validate files with extensions to their actual image type. It won't work with files without extensions, and neither will the UNIX file command, or even Spotlight's mdls utility that thinks image files without extensions are just public.data.


There are no tools available in macOS that can explore the internal image data, and arrive at the accurate extension information — except the third-party exiftool which you indicated was installed last Fall. Am I correct that your current images without extensions are only camera RAW images that may be RAF, CR2, or DNG image types?


This morning, using the same image data as last Fall, I wrote and tested a very short (8 lines) Zsh script that recursively retrieves all subordinate images of a parent directory and uses exiftool to peek inside them for their FileType. This is also the uppercase extension from the first paragraph that should be assigned to the raw image, and I use that in the renaming. When tested against the same images as I used last Fall for your other solution, the renaming was 100% accurate using known raw files.


You can run this script from the Terminal after making it executable. I have a Test4 directory on my Desktop. Do not use tilde path shorthand, as Zsh doesn't expand tilde without additional help:


cd Desktop
chmod +x addext.zsh
./addext.zsh ./Test4
Script has completed.


Copy and paste the following into BBEdit (which you also installed last Fall), and then save on your Desktop as addext.zsh.


#!/bin/zsh

: <<'COMMENT'

Recursively drill into directory hierarchy for image files with no
extension. Exclude text files. Use exiftool to inspect the image
and extract FileType (extension), then rename with that extension.

Requires third-party exiftool installation.

Usage: addext.zsh /path/to/parent/directory

VikingOSX, 2020-05-22, Apple Support Communities, No warranties of any kind.

COMMENT

STARTDIR="$1:a"
setopt extended_glob
for f in ${STARTDIR}/**/*~*.txt(.N);
do
    # print "${f}"
    EXT=$(/usr/local/bin/exiftool -s3 "-FileType" "${f}")
    mv "${f}" "${f}.${EXT}"
done
echo "Script has completed."


Before:


After:




Similar questions

46 replies
Question marked as Top-ranking reply

May 22, 2020 7:33 AM in response to Paul1762

Hi Paul,


The original post is here — for image validation on files with extensions.


The original script that I wrote last Fall was used to validate files with extensions to their actual image type. It won't work with files without extensions, and neither will the UNIX file command, or even Spotlight's mdls utility that thinks image files without extensions are just public.data.


There are no tools available in macOS that can explore the internal image data, and arrive at the accurate extension information — except the third-party exiftool which you indicated was installed last Fall. Am I correct that your current images without extensions are only camera RAW images that may be RAF, CR2, or DNG image types?


This morning, using the same image data as last Fall, I wrote and tested a very short (8 lines) Zsh script that recursively retrieves all subordinate images of a parent directory and uses exiftool to peek inside them for their FileType. This is also the uppercase extension from the first paragraph that should be assigned to the raw image, and I use that in the renaming. When tested against the same images as I used last Fall for your other solution, the renaming was 100% accurate using known raw files.


You can run this script from the Terminal after making it executable. I have a Test4 directory on my Desktop. Do not use tilde path shorthand, as Zsh doesn't expand tilde without additional help:


cd Desktop
chmod +x addext.zsh
./addext.zsh ./Test4
Script has completed.


Copy and paste the following into BBEdit (which you also installed last Fall), and then save on your Desktop as addext.zsh.


#!/bin/zsh

: <<'COMMENT'

Recursively drill into directory hierarchy for image files with no
extension. Exclude text files. Use exiftool to inspect the image
and extract FileType (extension), then rename with that extension.

Requires third-party exiftool installation.

Usage: addext.zsh /path/to/parent/directory

VikingOSX, 2020-05-22, Apple Support Communities, No warranties of any kind.

COMMENT

STARTDIR="$1:a"
setopt extended_glob
for f in ${STARTDIR}/**/*~*.txt(.N);
do
    # print "${f}"
    EXT=$(/usr/local/bin/exiftool -s3 "-FileType" "${f}")
    mv "${f}" "${f}.${EXT}"
done
echo "Script has completed."


Before:


After:




May 21, 2020 1:09 PM in response to John Galt

John,

hope I have this correct

in the Run Shell Script, I have this.

!/bin/zsh

# Note: use zsh -vx for debugging

# Zsh home: http://zsh.sourceforge.net/


# Recursively look for image files with wrong extension for mimetype

# and correct those extensions.


# usage: ./imgmv.zsh /path/to/parent/folder


zmodload zsh/regex


# global variables are denoted with -g

typeset -g mimetype

# arrays

typeset -ga mstatus

typeset -ga result=()

typeset -gA assoc=(dng image/x-adobe-dng cr2 image/x-canon-cr2 cr3 image/x-canon-cr3 raf image/x-fujifilm-raf tif image/tiff jpg image/jpeg)


function verify_file_type () {

local img_file=$1

local code=""

# sniff the first byte of the image file, without newline

code=$(od -t x1 -N 1 $img_file | awk '{$1=$1;print $2}')

if [[ $code = ff ]];

then

# get lower-case extension (:l:e) of this img_file

echo "image/jpeg ${img_file:l:e}"

elif [[ $code = 4d ]];

then

echo "image/tiff ${img_file:l:e}"

elif [[ $code =~ '00|46|49' ]]

then

echo "RAW ${img_file:l:e}"

else

echo "$code ${img_file:l:e}"

fi

return

}


function contains () {

# Lookup image extension as a key in associative array

# to see if it matches (true) or not (false) the mimetype

local mtype=$1

local extype=$2

# get the value associated with the extension key and compare to mimetype

[[ ${(v)assoc[$extype]} = $mtype ]] && echo true || echo false

return

}


function valid_image_ext () {

# return true when mimetype and extension are correct

local img_file=$1

local truth=""

# assign function output as regular array elements

# result[1] will be mimetype, and result[2] is the image extension

result=($(verify_file_type $img_file))

# see if extension is either of jpg or tiff

[[ $result[2] =~ 'jpg|tif' ]] && truth=true || truth=false

# does it match image/jpeg or image/tiff

if [[ $result[1] =~ 'i*(jpeg|tiff)' && $truth = true ]];

then

mimetype=$result[1]

echo "true $mimetype"

# extension does not match this mimetype

elif [[ $result[1] =~ 'i*(jpeg|tiff)' && $truth = false ]];

then

mimetype=$result[1]

echo "false $mimetype"

# otherwise it is a camera raw file with some extension

elif [[ $result[1] = RAW ]];

then

# get the Camera Raw mimetype string

mimetype=$(/usr/local/bin/exiftool -s3 -MIMEType $img_file)

# does the current image extension match the mimetype

# send back "true|false mimetype" to array mstatus

echo "$(contains $mimetype $result[2]) $mimetype"

fi

return

}


function rename_ext () {

# use mimetype (value) to lookup proper extension (key) in

# associative array and use that extension for the rename.

local mtype=$1

local img_file=$2

local extkeyname=${(k)assoc[(r)$mtype]}

# force raw extensions to upper-case

# force RAW file extensions to upper-case (:u) and others to lower (:l)

[[ $extkeyname =~ 'dng|cr2|raf' ]] && ext=${extkeyname:u} || ext=${extkeyname:l}

# tack extension onto full path and basename (a:r)

mv ${img_file} ${img_file:a:r}.$ext

return

}


startdir=$1

setopt GLOB_STAR_SHORT

# case-insensitive extension match

setopt no_CASE_GLOB

# if you add additional extensions here, add them in the associative array too

# tiff and jpeg are illegal extension formats, so not included here. The

# zsh (.) means to get just the paths to files, not folders.

for f in ${startdir}/**.(jpg|tif|cr2|dng|raf)(.); do

setopt CASE_GLOB

# mstatus[1] = true|false, mstatus[2]=mimetype

mstatus=($(valid_image_ext $f))

# true means the mimetype and extension match so fetch next file

[[ $mstatus[1] = true ]] && continue

# remove comment in print statement to generate a report prior to rename

# e.g. imgmv.zsh path >& ~/Desktop/rpt.txt

# print $mstatus[2] $f

$(rename_ext $mstatus[2] $f)

done

exit


and in the Run AppleScript I have this


use scripting additions




on run {input, parameters}


display alert "Change File Extension" message "Completed" as informational


return input


end run


hope this helps...


Paul

May 21, 2020 6:19 PM in response to Paul1762

Try using the file command on the files. I believe that that will try to determine the type of file even if the suffix is missing.


BradleyRossMacBook:Pictures bradleyross$ cp gingeravatar2.jpg working/gingeravatar


BradleyRossMacBook:Pictures bradleyross$ cd working


BradleyRossMacBook:working bradleyross$ file *


gingeravatar: JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=5, orientation=upper-left, xresolution=74, yresolution=82, resolutionunit=2], baseline, precision 8, 143x136, components 3


BradleyRossMacBook:working bradleyross$ 


The --extension of the file command gives the allowed suffixes. (See man file)


BradleyRossMacBook:working bradleyross$ file --extension *


gingeravatar: jpeg/jpg/jpe/jfif


BradleyRossMacBook:working bradleyross$ 

May 21, 2020 4:12 PM in response to Paul1762

Thanks Paul. Yeah I don't want to work with that. Seems complicated but that's only because I didn't write it.


In the interim, could you please do the following?


Open Terminal and copy / paste (do not type) the following:


file -I 


There needs to be a single space character after the last character, which is the reason to copy / paste.


Then, drag an image file icon into the Terminal window. Don't press Return just yet.


Then, copy / paste


 | perl -F/ -lane 'print $F[-1]' | awk '{print $1}' | sed 's/.$//'


... after which you can finally press Return.


You will get output resembling the following, using a .pdf as an example:


iMac22:~ john$ file -I /Users/john/Desktop/test.pdf | perl -F/ -lane 'print $F[-1]' | awk '{print $1}' | sed 's/.$//'
pdf
iMac22:~ john$ 


For a .png example:


iMac22:~ john$ file -I /Users/john/Desktop/test.png | perl -F/ -lane 'print $F[-1]' | awk '{print $1}' | sed 's/.$//'
png
iMac22:~ john$ 


Repeat for each type of file that you need to rename (.raf .dng .cr2).


This assumes you have a representative copy of each of those three file types. I don't happen to have any which is the reason you need to test the above. Include other image file types if you need to rename them also.


Confirm that the results of the above script will be the file extensions you want to append.


If it is, perhaps I can come up with a script. Maybe it will even work. No promises. As you can see from the above awful hideous attempts to extract something as simple as a file type it is certain to be an ugly mess so just be sure you have that backup 😮

May 23, 2020 10:50 AM in response to Paul1762

That /usr/local/bin/lib/image is a non-standard location for an exiftool installation. For now, just replace the /usr/local/bin/exiftool path in the script with /usr/local/bin/lib/image/exiftool — so the script can find it. It was also important that you changed Pass input to as arguments. With those two changes, the Automator application should work now.

May 26, 2020 10:39 AM in response to Paul1762

Good.


If you encounter any more of those rename failures ending in a period, it is because the associative array does not have an entry in it for the particular image extension, and the key lookup fails. These need to be entered in pairs (e.g. raf RAF, crw CRW, etc.). ExifTool will work with an extensionless filename to show you the real FileTypeExtension that should be on the image.

May 22, 2020 7:49 AM in response to VikingOSX

Errata. In case there are any images that already have an extension, we need to test for that, and ignore them. The following change provides that extra precaution to avoid redundantly adding to an existing extension. Update this code segment in the previously provided script:


    EXT=$(/usr/local/bin/exiftool -s3 "-FileType" "${f}")
    # skip those files that already have an extension
    [[ ${f:e} ]] && continue
    mv "${f}" "${f}.${EXT}"



May 21, 2020 5:36 PM in response to John Galt

John,

I have done that... not sure what it says though... I try a couple of different files...


MacBook Pro: ~ % file -I /Volumes/PR_500/Rec_Stock/2020_May_02372 | perl -F/ -lane 'print $F[-1]' | awk '{print $1}' | sed 's/.$//'


tiff


MacBook Pro: ~ % file -I /Volumes/PR_500/Rec_Stock/2020_May_01222 | perl -F/ -lane 'print $F[-1]' | awk '{print $1}' | sed 's/.$//'


octet-stream


MacBook Pro: ~ % file -I /Volumes/PR_500/Rec_Stock/2020_May_01442 | perl -F/ -lane 'print $F[-1]' | awk '{print $1}' | sed 's/.$//'


tiff


MacBook Pro: ~ % file -I /Volumes/PR_500/Rec_Stock/2020_April_01891 | perl -F/ -lane 'print $F[-1]' | awk '{print $1}' | sed 's/.$//'


octet-stream


MacBook Pro: ~ % file -I /Volumes/PR_500/Rec_Stock/2020_May_01222.raf | perl -F/ -lane 'print $F[-1]' | awk '{print $1}' | sed 's/.$//'


octet-stream


MacBook Pro: ~ % file -I /Users/Paul/Pictures/HSP\ MC2\ Homework\ May21_2.jpg | perl -F/ -lane 'print $F[-1]' | awk '{print $1}' | sed 's/.$//'


jpeg


MacBook Pro: ~ % file -I /Volumes/PR_500/Rec_Stock/FUJIFILM_X-T31861.RAF | perl -F/ -lane 'print $F[-1]' | awk '{print $1}' | sed 's/.$//'


octet-stream


MacBook Pro: ~ % file -I /Volumes/PR_500/Rec_Stock/2020_May_01222 | perl -F/ -lane 'print $F[-1]' | awk '{print $1}' | sed 's/.$//'


octet-stream


MacBook Pro: ~ % 


is this correct?


Paul

May 21, 2020 6:05 PM in response to John Galt

John,

I only tried some with extensions to see what happens with the command line... all the files I am looking at are all without extension.


when I tried the command line again with this MacBook Pro: ~ % file -I /Volumes/PR_500/Rec_Stock/2020_May_01812 | perl -F/ -lane 'print $F[-1]' | awk '{print $1}' | sed 's/.$//'

octet-stream.


when I change the extension to .RAF and open it the EXIF data tells me that it was shot using a FUJI Camera X-Pro 2...


so I guess octet-stream is .RAF


Paul

May 22, 2020 7:01 AM in response to Paul1762

I haven't forgotten about you Paul. Since if-then loops are unwieldy in bash I spent a lot of time attempting to incorporate my idea into a more readable AppleScript but got frustrated because the AppleScript "do shell script" command isn't doing what I would like it to do.


In case you're interested what I'd like to do is pass the file name to


file -I /Volumes/PR_500/image_file | perl -F/ -lane 'print $F[-1]' | awk '{print $1}' | sed 's/.$//'


.... which returns a nicely truncated jpg or png or whatever that could simply be appended to that file name, but getting the file name (image_file in the above) is proving to be difficult.


I would prefer an AppleScript but may abandon that line of thought and just go back to a bash one-liner.


I cannot find the post to be able to look at the discussion thread...


VikingOSX probably remembers it but if you're a glutton for punishment you could use this site's Search function, which is capable of finding Discussions using "Search by author". Be advised Search is horrendously broken and has been that way for so long that I doubt it will ever be fixed. I attempted to find what you're looking for but I can only take so much abuse.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

Rename Files Without Extension

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.