Мне понадобилось написать своей renamer для фото.

Зачем? Ведь есть куча бесплатного софта для пакетного переименовывания файлов. Я попробовал несколько, и в моем случае они были бесполезны, т.к. мне нужно было в качестве имени файла указывать инфу находящуюся в метаданных. А набор этих метаданных у разных форматов файлов разный (в моем случае JPG и MOV). Причем мне нужны были нужны метаданные, так как я переименовывал файлы скаченные с GooglePhoto, и у файла меняется ДатаСоздания и ДатаИзменения на текущую. И единственный способ узнать дату, когда сделано фото - это лезть в метаданные.

Я решил, что ChatGPT быстрее меня сможет найти библиотеки на java для этого, и поэтому обратился к нему. И, спойлер, он не подвёл.

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.quicktime.QuickTimeMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import com.drew.metadata.mov.QuickTimeMovieHeaderDirectory;

public class RenameFilesExample {
    public static void main(String[] args) {
        String folderPath = "path/to/folder";
        File folder = new File(folderPath);
        if (!folder.isDirectory()) {
            System.out.println("Specified path is not a folder");
            return;
        }

        File[] files = folder.listFiles();
        for (File file : files) {
            try {
                if (file.isFile()) {
                    String newName = getNewFileName(file);
                    File newFile = new File(folderPath + "/" + newName);
                    boolean success = file.renameTo(newFile);
                    if (!success) {
                        System.out.println("Could not rename file: " + file.getName());
                    }
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    private static String getNewFileName(File file) throws IOException {
        String extension = getFileExtension(file.getName()).toLowerCase();
        Metadata metadata;
        String dateStr;
        switch (extension) {
            case "jpg":
            case "jpeg":
                metadata = ImageMetadataReader.readMetadata(file);
                ExifSubIFDDirectory directory = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
                Date date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);
                dateStr = formatDate(date);
                break;
            case "mov":
                metadata = QuickTimeMetadataReader.readMetadata(file);
                QuickTimeMovieHeaderDirectory headerDirectory = metadata.getFirstDirectoryOfType(QuickTimeMovieHeaderDirectory.class);
                date = headerDirectory.getDate(QuickTimeMovieHeaderDirectory.TAG_CREATION_TIME);
                dateStr = formatDate(date);
                break;
            default:
                dateStr = "";
                break;
        }
        return dateStr + "." + extension;
    }

    private static String getFileExtension(String fileName) {
        int dotIndex = fileName.lastIndexOf('.');
        if (dotIndex == -1 || dotIndex == fileName.length() - 1) {
            return "";
        } else {
            return fileName.substring(dotIndex + 1);
        }
    }

    private static String formatDate(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        return dateFormat.format(date);
    }
}

Тут я создал проект и скопировал себе этот код. Но оказалось, что одна из библиотек, которую использовать ChatGPT отсутcвует в mvn central.

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.quicktime.QuickTimeMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import org.mp4parser.IsoFile;
import org.mp4parser.boxes.iso14496.part12.MovieHeaderBox;

public class RenameFilesExample {
    public static void main(String[] args) {
        String folderPath = "path/to/folder";
        File folder = new File(folderPath);
        if (!folder.isDirectory()) {
            System.out.println("Specified path is not a folder");
            return;
        }

        File[] files = folder.listFiles();
        for (File file : files) {
            try {
                if (file.isFile()) {
                    String newName = getNewFileName(file);
                    File newFile = new File(folderPath + "/" + newName);
                    boolean success = file.renameTo(newFile);
                    if (!success) {
                        System.out.println("Could not rename file: " + file.getName());
                    }
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    private static String getNewFileName(File file) throws IOException {
        String extension = getFileExtension(file.getName()).toLowerCase();
        Metadata metadata;
        String dateStr;
        switch (extension) {
            case "jpg":
            case "jpeg":
                metadata = ImageMetadataReader.readMetadata(file);
                ExifSubIFDDirectory directory = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
                Date date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);
                dateStr = formatDate(date);
                break;
            case "mov":
                IsoFile isoFile = new IsoFile(file);
                MovieHeaderBox movieHeaderBox = isoFile.getMovieBox().getMovieHeaderBox();
                Date creationTime = new Date(movieHeaderBox.getCreationTime().getTime() * 1000);
                dateStr = formatDate(creationTime);
                break;
            default:
                dateStr = "";
                break;
        }
        return dateStr + "." + extension;
    }

    private static String getFileExtension(String fileName) {
        int dotIndex = fileName.lastIndexOf('.');
        if (dotIndex == -1 || dotIndex == fileName.length() - 1) {
            return "";
        } else {
            return fileName.substring(dotIndex + 1);
        }
    }

    private static String formatDate(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        return dateFormat.format(date);
    }
}

В итоге я взял этот код, последние версии использованных в нем библиотек и вставил путь в папке с тысячами фоток и видео. И вуаля.

Получается, за 20 мин я получил от ChatGPT рабочий софт, который отлично выполнил необходимую мне задачу. Имхо, на поиски существующего софта и настройку его работы ушло бы сильно больше времени.

Ну и конечно я запушил этот код на gitHub.

Комментарии (7)


  1. fire64
    13.04.2023 10:51
    +2

    Chatgpt достаточно удобен для написания простых скриптов и небольших программ.

    Сам использую его для написания Python скриптов для автоматизации действий.


  1. SimSonic
    13.04.2023 10:51
    +1

    Тоже за 2 недели раза три помог мне найти решение, над которым не хотелось ломать голову.


  1. Squoworode
    13.04.2023 10:51
    +7

    Total Commander в пакетном переименовании спокойно использует любые метаданные, как доступные системе, так и формируемые плагинами


  1. b00
    13.04.2023 10:51
    +1

    Прямо с импортов - подвёл. Давно устаревшее API дат подсунул. Ну, т.е., в контексте задачи "одноразовый скрипт" - он справился. Хотя зачем на Java её решать тогда...


  1. snobit
    13.04.2023 10:51
    +3

    String folderPath = "path/to/folder";
    Каждый раз будете в коде менять папку?

    return dateStr + "." + extension;
    Может вернуть ".", что тогда будет?

    В качестве замене гугла может и не плохо, но головой думать все еще надо.


    1. ZenDayawrk
      13.04.2023 10:51

      Недавно надо было писать скрипт небольшой на поше, он его написал, но местами он был не оптимизирован, я попытался научить GPT назвав места где можно улучшить, дальше я продолжил уточнять детали моего алгоритма у GPT и он дополнял существующий скрипт с моими правками, а через 3 вопроса-ответа он снова забил на мои правки и писал те строки которые изначально были им встроены :)

      Так что думать надо)


  1. akhmelev
    13.04.2023 10:51

    Ну и конечно я запушил этот код на gitHub.

    ...чтобы следующие версии роботов после скана кодовой базы учились уже у роботов, а не у людей. Шел две тысячи двадцать девятый год и skynet был на распутье...