根据拍摄时间一键将图片分组

说在前面

最近裸辞出去玩了两个多月,旅行的过程中少不了拍照,祖国的大好河山太美了,一趟旅行下来产出了1w多张图片,所以回来后总要整理一下图片,我这边想要的是根据拍摄时间来对图片进行分组,所以回到家后我就写了这样一个脚本来处理图片。

工具实现

1、模块导入

  • inquirer

通过require(“@jyeontu/j - inquirer”)导入,用于创建命令行交互,让用户选择需要分组的目录。

  • fs

使用require(“fs”)导入,用于进行文件系统的操作,如读取目录内容(readdirSync)、获取文件状态(statSync)、创建文件夹(mkdirSync)以及复制文件(copyFileSync)等操作。
path模块:通过require(“path”)导入,用于处理文件路径,如拼接路径(join)等操作。

  • exif

使用require(“exif”).ExifImage导入,用于读取图片的 Exif 数据,以便获取图片的拍摄时间。

2、获取图片拍摄时间

function getPictureTakingTime(imagePath) {
  return new Promise((resolve) => {
    try {
      new ExifImage({ image: imagePath }, function (error, exifData) {
        if (error) {
          resolve(null);
        } else {
          if (exifData && exifData.exif) {
            const takingTime = exifData.exif.DateTimeOriginal;
            resolve(takingTime);
          } else {
            resolve(null);
          }
        }
      });
    } catch (error) {
      resolve(null);
    }
  });
}
  • 函数接受一个图片路径imagePath作为参数,并返回一个Promise。
  • 在函数内部,通过new ExifImage来尝试读取图片的 Exif 数据。如果读取过程中出现错误(error)或者图片没有 Exif 数据(exifData && exifData.exif不满足),则Promise返回null;如果成功读取到 Exif 数据并且包含DateTimeOriginal属性(表示拍摄时间),则将该拍摄时间作为Promise的结果返回。

3、通过交互获取需要分组的目录

const baseDir = process.cwd();
const options = [
  {
    type: "folder",
    message: "请选择需要分组的目录:",
    name: "directory",
    default: "",
    dirname: baseDir,
  },
];
const answers = await new inquirer(options).prompt();
const dirPath = answers.directory;
  • 首先获取当前工作目录(process.cwd())作为基础目录baseDir。
  • 通过inquirer创建一个交互选项,提示用户选择需要分组的目录。用户选择的结果存储在answers.directory中,即dirPath变量。

4、遍历文件并分组

const files = fs.readdirSync(dirPath);
const map = {};
let sum = 0;
console.log(`正在获取图片信息,请稍等……`);
for (const file of files) {
  const newPath = path.join(dirPath, file);
  const info = fs.statSync(newPath);
  if (!info.isFile()) {
    continue;
  }
  sum++;
  const m = (await getPictureTakingTime(newPath)) || dateFormat(info.mtime);
  const mArr = m.split(" ");
  mArr[0] = mArr[0].split(":").join("-");
  const mtime = dateFormat(mArr.join(" "));
  if (!map[mtime]) {
    map[mtime] = [];
  }
  map[mtime].push(file);
}
  • 使用fs.readdirSync(dirPath)读取目标目录下的所有文件和文件夹。
  • 创建一个空对象map用于存储分组信息。
  • 定义变量sum用于统计文件数量,初始值为 0。
  • 遍历目标目录下的每个文件:
    • 通过path.join(dirPath, file)构建文件的完整路径newPath。
    • 使用fs.statSync(newPath)获取文件状态信息info,如果不是文件(!info.isFile())则跳过该文件。
    • 对于每个文件,sum自增 1,并尝试获取图片拍摄时间。如果getPictureTakingTime(newPath)返回null(即没有拍摄时间 Exif 数据),则使用dateFormat(info.mtime)对文件修改时间进行格式化;否则使用拍摄时间。
    • 对获取到的时间进行处理,将时间字符串中的:替换为-,然后再使用dateFormat进行格式化,得到最终的日期格式mtime。
    • 如果map中不存在以mtime为键的属性,则创建一个空数组作为值;然后将文件名称添加到对应的日期数组中。

5、创建分组目录并移动文件

for (const key in map) {
  const keyPath = path.join(dirPath, key);
  if (!fs.existsSync(keyPath)) {
    fs.mkdirSync(keyPath);
  }
  for (const p of map[key]) {
    const np = path.join(keyPath, p);
    if (fs.existsSync(np)) {
      continue;
    }
    fs.copyFileSync(path.join(dirPath, p), path.join(keyPath, p));
  }
}
  • 遍历map中的每个日期键key:
    • 通过path.join(dirPath, key)构建分组文件夹的路径keyPath。
    • 如果该文件夹不存在(!fs.existsSync(keyPath)),则使用fs.mkdirSync(keyPath)创建文件夹。
    • 遍历每个日期对应的文件数组中的文件p:
      • 通过path.join(keyPath, p)构建目标文件路径np。
      • 如果目标文件已经存在(fs.existsSync(np)),则跳过;否则使用fs.copyFileSync将文件从源路径(path.join(dirPath, p))复制到目标路径。

使用

该工具已经发布到 npm 上,可以直接通过命令npm i -g jyeontu进行安装,安装完后在控制台中输入jyeontu file即可进行操作。选择图片分组即可:

源码

Gitee

该工具的源码也已经开源,有兴趣的同学可以到Gitee上查看:https://gitee.com/zheng_yongtao/node-scripting-tool/tree/master/src/jyeontu

欢迎star~

公众号

关注公众号『前端也能这么有趣』,获取更多有趣内容。

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/887788.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

通信工程学习:什么是ICP网络内容服务商

ICP:网络内容服务商 ICP,全称Internet Content Provider,即网络内容服务商,是指那些通过互联网向用户提供各种类型内容服务的组织或个人。ICP在数字化时代扮演着至关重要的角色,它们不仅是信息的传播者,更是…

Linux高级编程_29_信号

文章目录 进程间通讯 - 信号信号完整的信号周期信号的编号信号的产生发送信号1 kill 函数(他杀)作用:语法:示例: 2 raise函数(自杀)作用:示例: 3 abort函数(自杀)作用:语法:示例: 4 …

苏州 数字化科技展厅展馆-「世岩科技」一站式服务商

数字化科技展厅展馆设计施工是一个综合性强、技术要求高的项目,涉及到众多方面的要点。以下是对数字化科技展厅展馆设计施工要点的详细分析: 一、明确目标与定位 在设计之初,必须明确展厅的目标和定位。这包括确定展厅的主题、目标受众、展…

详解正确创建好SpringBoot项目后但是找不到Maven的问题

目录 问题 解决步骤: 找到File->Project Structure... 设置SDK 设置SDKs 问题 刚刚在使用IDEA专业版创建好SpringBoot项目后,发现上方导航栏的运行按钮是灰色的,而且左侧导航栏的pom.xml的图标颜色也不是正常的,与此同时我…

PIKACHU | PIKACHU 靶场 XSS 后台配置

关注这个靶场的其他相关笔记:PIKACHU —— 靶场笔记合集-CSDN博客 PIKACHU 自带了一个 XSS 平台,可以辅助我们完成 XSS 攻击,但是该后台需要配置数据库以后才能使用。本教程,就是教大家如何配置 PIKACHU XSS 平台的。 PIKACHU XS…

在线教育的未来:SpringBoot技术实现

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理微服务在线教育系统的相关信息成为必然。开…

Hadoop大数据入门——Hive-SQL语法大全

Hive SQL 语法大全 基于语法描述说明 CREATE DATABASE [IF NOT EXISTS] db_name [LOCATION] path; SELECT expr, ... FROM tbl ORDER BY col_name [ASC | DESC] (A | B | C)如上语法,在语法描述中出现: [],表示可选,如上[LOCATI…

基于深度学习的乳腺癌分类识别与诊断系统

温馨提示:文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 乳腺癌是全球最常见的癌症之一,早期诊断对于治疗效果至关重要。近年来,深度学习技术在医学图像分析领域取得了显著进展,能够从大量的医学影像数据中自动学习和提…

【Android 14源码分析】WMS-窗口显示-第一步:addWindow

忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。                                                                                  – 服装…

网络安全概述:从认知到实践

一、定义 网络安全,即致力于保护网络系统所涵盖的硬件、软件以及各类数据,切实保障其免遭破坏、泄露或者篡改等不良情形的发生。 二、重要性 个人层面:着重于守护个人隐私以及财产安全,为个人在网络世界中的各项活动提供坚实的保…

Redis篇(Redis原理 - 数据结构)(持续更新迭代)

目录 一、动态字符串 二、intset 三、Dict 1. 简介 2. Dict的扩容 3. Dict的rehash 4. 知识小结 四、ZipList 1. 简介 2. ZipListEntry 3. Encoding编码 五、ZipList的连锁更新问题 六、QuickList 七、SkipList 八、RedisObject 1. 什么是 redisObject 2. Redi…

使用JavaScript写一个网页端的四则运算器

目录 style(内联样式表部分) body部分 html script 总的代码 网页演示 style(内联样式表部分) <style>body {font-family: Arial, sans-serif;display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #f0f0f0;}.calculator {…

Python开发环境配置(mac M2)

1. 前言 作为一名程序员&#xff0c;工作中需要使用Python进行编程&#xff0c;甚至因为项目需要还得是不同版本的Python如何手动管理多个版本的Python&#xff0c;如何给Pycharm&#xff08;IDE&#xff09;配置对应的interpreter等&#xff0c;都成为一个 “不熟练工” 的难…

使用百度文心智能体创建多风格表情包设计助手

文章目录 一、智能定制&#xff0c;个性飞扬二、多元风格&#xff0c;创意无限 百度文心智能体平台为你开启。百度文心智能体平台&#xff0c;创建属于自己的智能体应用。百度文心智能体平台是百度旗下的智能AI平台&#xff0c;集成了先进的自然语言处理技术和人工智能技术&…

基于SpringBoot实现QQ邮箱发送短信功能 | 免费短信服务

开发学习过程中有个短信发送功能&#xff0c;阿里云腾讯云等等都要money&#xff0c;听说qq邮箱可以实现免费发送邮箱的功能&#xff08;短信发送的平替&#xff09;&#xff0c;就用这个来实现&#xff01;&#xff01;&#xff01;【找了好多好多方法才成功的啊啊啊啊&#x…

【Linux】进程第三弹(虚拟地址空间)

目录 现象 底层原因 数据不发生修改 数据修改 小总结 地址空间本质 为什么要有地址空间 现象 来看代码&#xff1a; #include <stdio.h> #include <unistd.h> #include <sys/types.h>int val 50;int main() {printf("father process is running…

标准正态分布的数据 tensorflow 实现正态分布图,python 编程,数据分析和人工智能

import tensorflow as tf import matplotlib.pyplot as plt # 设置随机种子以获得可重复的结果 tf.random.set_seed(42) # 生成正态分布的数据 # mean0 和 stddev1 表示生成标准正态分布的数据 # shape(1000,) 表示生成1000个数据点 data tf.random.normal(mean0, stddev1, …

【python】追加写入excel

输出文件运行前&#xff08;有两张表&#xff0c;“表1”和“Sheet1”&#xff09;&#xff1a; 目录 一&#xff1a;写入单表&#xff08;删除所有旧工作表&#xff0c;写入新表&#xff09;二&#xff1a;写入多表&#xff08;删除所有旧工作表&#xff0c;写入新表&#x…

HTML5实现唐朝服饰网站模板源码

文章目录 1.设计来源1.1 网站首页-界面效果1.2 唐装演变-界面效果1.3 唐装配色-界面效果1.4 唐装花纹-界面效果1.5 唐装文化-界面效果 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcL…

[C++][第三方库][Websocket]详细讲解

目录 1.Websocket 协议1.介绍2.原理简介 2.Websocketpp1.介绍2.安装 3.常用接口4.使用 1.Websocket 协议 1.介绍 WebSocket是从HTML5开始支持的一种网页端和服务端保持长连接的消息推送机制产生原因&#xff1a; 传统的web程序都是属于"一问一答"的形式 即客户端给…