var cmd = DOpus.Create().Command(); var stt = DOpus.Create().StringTools(); var fsu = DOpus.FSUtil(); var fso = new ActiveXObject('Scripting.FileSystemObject'); var wsh = new ActiveXObject('WScript.Shell'); var exifTags = DOpus.Create().Map(); var exeExifTool = fsu.Resolve('/bin\\exiftool\\exiftool.exe'); // -- Adjust to your system. Use double backslashes. var cacheFolder = fsu.Resolve('/profile\\ExifToolCache'); // -- Adjust to your preferences. Use double backslashes. var maxCacheAge = 60; // Rebuild cache if older than ... minutes -- Adjust to your preferences var onAnyChange = false; // Rebuild cache if *any* change in the items' lastmodified fields is detected, not just changes after building the cache. Increases the time until the first column entries are shown! -- Adjust to your preferences var log = true; // -- Adjust to your preferences. Set to false if you don't want any logging // Column definitions go here. Make sure there is no comma in the last line before the closing bracket. // group, tag: reference for ExifTool (mandatory) // name, label, header: adjust to your preferences (optional) // justify: like Opus standard for columns (optional) // type: datetime, date, time, number. String, if left empty (optional) // defaultValue: value, if no tag is found via ExifTool (optional) // group, tag, name, label, header, defaultValue, justify, type var exifColumns = [ new DefineColumn('Canon', 'CanonExposureMode', '', '', '', '', '', ''), new DefineColumn('Canon', 'FocusMode', '', '', '', '', '', ''), new DefineColumn('Canon', 'MeteringMode', '', '', '', '', '', ''), new DefineColumn('Canon', 'NumAFPoints', '', '', '', '', '', 'number'), new DefineColumn('Canon', 'OneShotAFRelease', '', '', '', '', '', ''), new DefineColumn('Canon', 'ValidAFPoints', '', '', '', '', '', ''), new DefineColumn('Composite', 'Aperture', '', '', '', '', '', 'number'), new DefineColumn('Composite', 'AvgBitrate', '', '', '', '', '', ''), new DefineColumn('Composite', 'CircleOfConfusion', '', '', '', '', '', ''), new DefineColumn('Composite', 'Duration', '', '', '', '', '', ''), new DefineColumn('Composite', 'FOV', '', '', '', '', '', ''), new DefineColumn('Composite', 'FocalLength35efl', '', '', '', '', '', ''), new DefineColumn('Composite', 'HyperfocalDistance', '', '', '', '', '', ''), new DefineColumn('Composite', 'ImageSize', '', '', '', '', '', ''), new DefineColumn('Composite', 'LensID', '', '', '', '', '', ''), new DefineColumn('Composite', 'LightValue', '', '', '', '', '', ''), new DefineColumn('Composite', 'Megapixels', '', '', '', '', '', ''), new DefineColumn('Composite', 'Rotation', '', '', '', '', '', 'number'), new DefineColumn('Composite', 'ShootingMode', '', '', '', '', '', ''), new DefineColumn('Composite', 'ShutterSpeed', '', '', '', '', '', ''), new DefineColumn('Composite', 'SubSecCreateDate', '', '', '', '', '', 'datetime'), new DefineColumn('Composite', 'SubSecDateTimeOriginal', '', '', '', '', '', 'datetime'), new DefineColumn('Composite', 'SubSecModifyDate', '', '', '', '', '', 'datetime'), new DefineColumn('EXE', 'CompanyName', '', '', '', '', '', ''), new DefineColumn('EXE', 'MachineType', '', '', '', '', '', ''), new DefineColumn('EXE', 'SubsystemVersion', '', '', '', '', '', ''), new DefineColumn('EXE', 'TimeStamp', '', '', '', '', '', 'datetime'), new DefineColumn('EXIF', 'ApertureValue', '', '', '', '', '', ''), new DefineColumn('EXIF', 'CreateDate', '', '', '', '', '', 'datetime'), new DefineColumn('EXIF', 'DateTimeOriginal', '', '', '', '', '', 'datetime'), new DefineColumn('EXIF', 'ExposureCompensation', '', '', '', '', '', ''), new DefineColumn('EXIF', 'ExposureMode', '', '', '', '', '', ''), new DefineColumn('EXIF', 'ExposureProgram', '', '', '', '', '', ''), new DefineColumn('EXIF', 'ExposureTime', '', '', '', '', '', ''), new DefineColumn('EXIF', 'FNumber', '', '', '', '', '', ''), new DefineColumn('EXIF', 'Flash', '', '', '', '', '', ''), new DefineColumn('EXIF', 'FocalLength', '', '', '', '', '', ''), new DefineColumn('EXIF', 'LensInfo', '', '', '', '', '', ''), new DefineColumn('EXIF', 'LensModel', '', '', '', '', '', ''), new DefineColumn('EXIF', 'LensSerialNumber', '', '', '', '', '', ''), new DefineColumn('EXIF', 'Make', '', '', '', '', '', ''), new DefineColumn('EXIF', 'Model', '', '', '', '', '', ''), new DefineColumn('EXIF', 'ModifyDate', '', '', '', '', '', ''), new DefineColumn('EXIF', 'Orientation', '', '', '', '', '', ''), new DefineColumn('EXIF', 'XResolution', '', '', '', '', '', ''), new DefineColumn('EXIF', 'YResolution', '', '', '', '', '', ''), new DefineColumn('ExifIFD', 'DateTimeOriginal', '', '', '', '', '', 'datetime'), new DefineColumn('File', 'EncodingProcess', '', '', '', '', '', ''), new DefineColumn('File', 'FileAccessDate', '', '', '', '', '', 'datetime'), new DefineColumn('File', 'FileCreateDate', '', '', '', '', '', 'datetime'), new DefineColumn('File', 'FileModifyDate', '', '', '', '', '', 'datetime'), new DefineColumn('File', 'FileTypeExtension', '', '', '', '', '', ''), new DefineColumn('H264', 'ApertureSetting', '', '', '', '', '', ''), new DefineColumn('H264', 'DateTimeOriginal', '', '', '', '', '', 'datetime'), new DefineColumn('H264', 'ExposureProgram', '', '', '', '', '', ''), new DefineColumn('H264', 'ExposureTime', '', '', '', '', '', ''), new DefineColumn('H264', 'FNumber', '', '', '', '', '', 'number'), new DefineColumn('H264', 'Focus', '', '', '', '', '', ''), new DefineColumn('H264', 'Gain', '', '', '', '', '', ''), new DefineColumn('H264', 'ImageHeight', '', '', '', '', '', ''), new DefineColumn('H264', 'ImageStabilization', '', '', '', '', '', ''), new DefineColumn('H264', 'ImageWidth', '', '', '', '', '', ''), new DefineColumn('H264', 'Make', '', '', '', '', '', ''), new DefineColumn('H264', 'Model', '', '', '', '', '', ''), new DefineColumn('H264', 'TimeCode', '', '', '', '', '', ''), new DefineColumn('H264', 'WhiteBalance', '', '', '', '', '', ''), new DefineColumn('ID3', 'Genre', '', '', '', '', '', ''), new DefineColumn('ID3', 'ReleaseTime', '', '', '', '', '', 'datetime'), new DefineColumn('ID3', 'Subtitle', '', '', '', '', '', ''), new DefineColumn('ID3', 'Year', '', '', '', '', '', ''), new DefineColumn('M2TS', 'AudioBitrate', '', '', '', '', '', ''), new DefineColumn('M2TS', 'AudioChannels', '', '', '', '', '', ''), new DefineColumn('M2TS', 'AudioSampleRate', '', '', '', '', '', ''), new DefineColumn('M2TS', 'Duration', '', '', '', '', '', 'time'), new DefineColumn('M2TS', 'SurroundMode', '', '', '', '', '', ''), new DefineColumn('M2TS', 'VideoStreamType', '', '', '', '', '', ''), new DefineColumn('MakerNotes', 'CameraOrientation', '', '', '', '', '', ''), new DefineColumn('MakerNotes', 'CanonExposureMode', '', '', '', '', '', ''), new DefineColumn('MakerNotes', 'CanonFirmwareVersion', '', '', '', '', '', ''), new DefineColumn('MakerNotes', 'CanonModelID', '', '', '', '', '', ''), new DefineColumn('MakerNotes', 'ShutterCount', '', '', '', '', '', 'number'), new DefineColumn('MakerNotes', 'WhiteBalance', '', '', '', '', '', ''), new DefineColumn('Matroska', 'DateTimeOriginal', '', '', '', '', '', ''), new DefineColumn('Matroska', 'DisplayHeight', '', '', '', '', '', 'number'), new DefineColumn('Matroska', 'DisplayWidth', '', '', '', '', '', 'number'), new DefineColumn('Matroska', 'Duration', '', '', '', '', '', ''), new DefineColumn('Matroska', 'ImageHeight', '', '', '', '', '', 'number'), new DefineColumn('Matroska', 'ImageWidth', '', '', '', '', '', 'number'), new DefineColumn('Matroska', 'TrackNumber', '', '', '', '', 'number', ''), new DefineColumn('PDF', 'CreateDate', '', '', '', '', '', 'datetime'), new DefineColumn('PDF', 'Creator', '', '', '', '', '', ''), new DefineColumn('PDF', 'ModifyDate', '', '', '', '', '', 'datetime'), new DefineColumn('PDF', 'PageCount', '', '', '', '', '', 'number'), new DefineColumn('PDF', 'Producer', '', '', '', '', '', ''), new DefineColumn('PDF', 'Title', '', '', '', 'Move on. Nothing to see here but the PDF default value', 'left', ''), new DefineColumn('QuickTime', 'AudioAvgBitrate', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'CompressorID', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'ContentCreateDate', '', '', '', '', '', 'datetime'), new DefineColumn('QuickTime', 'CreateDate', '', '', '', '', '', 'datetime'), new DefineColumn('QuickTime', 'CreationDate', '', '', '', '', '', 'datetime'), new DefineColumn('QuickTime', 'DateAcquired', '', '', '', '', '', 'datetime'), new DefineColumn('QuickTime', 'DateTimeOriginal', '', '', '', '', '', 'datetime'), new DefineColumn('QuickTime', 'Duration', '', '', '', '', '', 'time'), new DefineColumn('QuickTime', 'EncodingTime', '', '', '', '', '', 'datetime'), new DefineColumn('QuickTime', 'LocationDate', '', '', '', '', '', 'datetime'), new DefineColumn('QuickTime', 'MajorBrand', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'Make', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'MediaCreateDate', '', '', '', '', '', 'datetime'), new DefineColumn('QuickTime', 'MediaDuration', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'MediaModifyDate', '', '', '', '', '', 'datetime'), new DefineColumn('QuickTime', 'MinorVersion', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'Model', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'ModifyDate', '', '', '', '', '', 'datetime'), new DefineColumn('QuickTime', 'Title', '', '', '', 'äöü ÄÖÜ ß', '', ''), new DefineColumn('QuickTime', 'TrackCreateDate', '', '', '', '', '', 'datetime'), new DefineColumn('QuickTime', 'TrackDuration', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'TrackModifyDate', '', '', '', '', '', 'datetime'), new DefineColumn('QuickTime', 'VideoAvgBitrate', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'VideoAvgFrameRate', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'VideoCodec', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'VideoFrameRate', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'VideoMaxBitrate', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'VideoMaxFrameRate', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'VideoSize', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'XResolution', '', '', '', '', '', ''), new DefineColumn('QuickTime', 'YResolution', '', '', '', '', '', ''), new DefineColumn('RIFF', 'AvgBytesPerSec', '', '', '', '', '', ''), new DefineColumn('RIFF', 'BitsPerSample', '', '', '', '', '', ''), new DefineColumn('RIFF', 'Encoding', '', '', '', '', '', ''), new DefineColumn('RIFF', 'NumChannels', '', '', '', '', '', ''), new DefineColumn('RIFF', 'SampleRate', '', '', '', '', '', ''), new DefineColumn('Sony', 'FocusMode', '', '', '', '', '', ''), new DefineColumn('XML', 'CreationDateValue', '', '', '', '', '', 'datetime'), new DefineColumn('XML', 'DeviceManufacturer', '', '', '', '', '', ''), new DefineColumn('XML', 'DeviceModelName', '', '', '', '', '', ''), new DefineColumn('XML', 'DeviceSerialNo', '', '', '', '', '', ''), new DefineColumn('XML', 'VideoFormatVideoFrameCaptureFps', '', '', '', '', '', ''), new DefineColumn('XML', 'VideoFormatVideoFrameFormatFps', '', '', '', '', '', ''), new DefineColumn('XML', 'VideoFormatVideoFrameVideoCodec', '', '', '', '', '', ''), new DefineColumn('XML', 'VideoFormatVideoLayoutNumOfVerticalLine', '', '', '', '', '', ''), new DefineColumn('XML', 'VideoFormatVideoLayoutPixel', '', '', '', '', '', ''), new DefineColumn('XMP', 'Contributor', '', '', '', '', '', ''), new DefineColumn('XMP', 'CreateDate', '', '', '', '', '', 'datetime'), new DefineColumn('XMP', 'Creator', '', '', '', '', '', ''), new DefineColumn('XMP', 'CreatorTool', '', '', '', '', '', ''), new DefineColumn('XMP', 'Date', '', '', '', '', '', 'datetime'), new DefineColumn('XMP', 'DateCreated', '', '', '', '', '', 'datetime'), new DefineColumn('XMP', 'Description', '', '', '', '', '', ''), new DefineColumn('XMP', 'Format', '', '', '', '', '', ''), new DefineColumn('XMP', 'Headline', '', '', '', '', '', ''), new DefineColumn('XMP', 'MetadataDate', '', '', '', '', '', 'datetime'), new DefineColumn('XMP', 'ModifyDate', '', '', '', '', '', 'datetime'), new DefineColumn('XMP', 'Producer', '', '', '', '', '', ''), new DefineColumn('XMP', 'Subject', '', '', '', '', '', ''), new DefineColumn('XMP', 'Title', '', '', '', '', 'left', ''), new DefineColumn('XMP', 'XMPToolkit', '', '', '', '', '', '') ]; function DefineColumn(group, tag, name, label, header, defaultValue, justify, type) { this.group = group; this.tag = tag; var tmp = (group + '-' + tag); this.name = name == '' ? tmp : name; this.label = label == '' ? tmp : label; this.header = header == '' ? tmp : header; this.defaultValue = defaultValue; this.justify = justify; this.type = type; } function OnInit(initData) { initData.name = 'ExifTool'; initData.desc = 'Provide columns for tags read via exiftool.exe'; initData.version = '2022-06-14'; initData.url = 'https://resource.dopus.com/t/exiftool-custom-columns/38975'; initData.default_enable = true; cmd.RunCommand('CreateFolder NAME="' + cacheFolder + '"'); Log('exeExifTool: ' + exeExifTool + (fsu.Exists(exeExifTool) ? ' - OK. File exists' : ' - Error. File not found!')); Log('cacheFolder: ' + cacheFolder + (fsu.Exists(cacheFolder) ? ' - OK. Folder exists' : ' - Error. Folder not found!')); } function OnAddColumns(AddColData) { for (var i = 0; i < exifColumns.length; ++i) { var column = exifColumns[i]; var col = AddColData.AddColumn(); col.multicol = true; col.name = column.name; col.label = column.label; col.header = column.header; col.justify = column.justify; col.type = column.type; col.method = 'OnColumn'; } } function OnColumn(scriptColData) { var item = scriptColData.item; if (item.is_dir) return; if (fsu.GetItem(item.path).InGroup('Archives')) return; // ExifTool can't read from archives (I think) var cacheFile = fsu.GetItem(cacheFolder + '\\' + String(item.realpath).replace(':', '') + '.txt'); var cutOffDate = DOpus.Create().Date(); cutOffDate.Sub(maxCacheAge, 'm'); // Current date minus ... minutes if (log) var startTime = DOpus.Create().Date(); if (!fsu.Exists(cacheFile) || fsu.GetItem(cacheFile.path).modify.Compare(cutOffDate) < 0 || fsu.GetItem(cacheFile.path).modify.Compare(item.modify) < 0 || (onAnyChange && cacheFile.modify.Compare(item.modify) != 0)) { Log('Processing ' + fso.GetFolder(item.path).files.count + ' files in "' + item.path + '" with ExifTool...', startTime); Log('- Cache (cacheFile.path): ' + cacheFile.path, startTime); Log('- Deleting cache', startTime); cmd.RunCommand('Delete FILE="' + cacheFile.path + '" QUIET'); Log('- Generating files', startTime); var cmdLine = '"' + exeExifTool + '" -short -duplicates -unknown -groupNames -tab -textOut! "' + cacheFile.path + '\\%f.%e.txt" -extension "*" "' + String(item.path).replace(/\\$/, '') + '"'; // ExifTool doesn't like the trailing slashes item.path produces for root folders like C:\ wsh.Run(cmdLine, 0, true); if (onAnyChange) { Log('- Setting lastmodifieddate for files', startTime); var folderEnum = fsu.ReadDir(cacheFile.path); while (!folderEnum.complete) { var folderItem = folderEnum.Next(); var origItem = fsu.GetItem(String(folderItem.realpath).substring(String(cacheFolder).length + 1).replace(/(.)(.*).txt/, '$1:$2')); cmd.RunCommand('SetAttr FILE="' + folderItem + '" META "lastmodifieddate:' + origItem.modify.Format('D#yyyy-MM-dd T#HH:mm:ss') + '"'); } folderEnum.Close(); } Log('- Setting lastmodifieddate for cache', startTime); cmd.RunCommand('SetAttr FILE="' + cacheFile.path + '" META "lastmodifieddate:' + DOpus.Create().Date().Format('D#yyyy-MM-dd T#HH:mm:ss') + '"'); Log('... done!', startTime); } if (!fsu.Exists(cacheFile)) { Log('*** Error: cache file could not be created! ***'); Log('item: ' + item); Log('cacheFile: ' + cacheFile); Log(''); Log('cmdLine:'); Log(cmdLine); Log(''); return; } exifTags.clear(); var cf = cacheFile.Open(); var cfBlob = cf.Read(); var strBlob = stt.Decode(cfBlob, 'utf8'); var arrBlob = strBlob.split('\r\n'); for (var i = 0; i < arrBlob.length; ++i) { var line = arrBlob[i].split('\t'); var group = line[0]; var tag = line[1]; var value = line[2]; var key = group + '-' + tag; exifTags(key) = value; } cf.Close(); for (var i = 0; i < exifColumns.length; ++i) { var column = exifColumns[i]; var key = column.group + '-' + column.tag; var value = exifTags.exists(key) ? exifTags(key) : column.defaultValue; if (value != '') { if (column.type == 'datetime' || column.type == 'date' || column.type == 'time') { value = DOpus.Create().Date(value.replace(/:/g, '')); } else if (column.type == 'number') { value = Number(value); } } scriptColData.columns(column.name).value = value; } } function Log(str, time) { if (!log) return; if (time) { var currTime = DOpus.Create().Date(); var gap = (currTime + currTime.ms - time - time.ms); DOpus.Output(padTime(gap) + ' ' + str); } else { DOpus.Output(str); } } function padTime(milliseconds) { var str = ('000000' + String(milliseconds)).slice(-6); var tmp = str.substring(0, 3) + ':' + str.substring(3, 6); tmp = tmp.replace(/^00/, ' '); tmp = tmp.replace(/^0/, ' '); return tmp; }