文章目录
引言
来自图片处理的需求:
raw/高精度jpg之类的图片单文件体积太大,出片之后选图很吃力,单张加载就要不少时间,还要经常来回比较两张图片,有时还要把图片包发给别人让他们自己挑,所以选片时往往用的是缩图后的jpg文件(快照)。
但基于选好的快照去找原图也是个麻烦事,要一张一张找,一不小心就盯错行。
解决方案:
所以花了好半天功夫写了这个脚本:
- 把挑好的jpg文件放进原图文件夹,运行一下脚本,没选上的原图就都会被放进一个叫“files to delete”的子文件夹,然后是删是保留就看您自己的了。
脚本使用方法:
1.安装python 3
官网下载python3.0系列(https://www.python.org)
下载3.0以上的任意版本的“Windows x86 web-based installer”并进行安装
2.新建一个TXT文件,拷入下面代码后保存,并将后缀名改为”.py”
代码:
#!/usr/bin/ env python
#coding=UTF-8
import os, shutil
import sys
#*************** 脚本说明: ***************
#脚本作用是以文件名和后缀类型为判断依据,移动没有快照文件的文件到待删除目录
#不支持文件名相同但内容不同的情况
#对文件夹内所有目录和子目录生效
#*************** 使用方法: *************** by:一个伪互联网球迷
# 环境要求:Windows + 已经安装3.0及以上版本的python
# 1.把要整理的照片的raw文件以及本脚本放在一个文件夹内
# 2.用光影魔术手之类的格式转换软件把这些raw转换成jpg,放进一个子文件夹
# 3.用任意图片浏览器浏览jpg,删除不需要的照片
# 4.用python集成进鼠标右键的“Edit with IDLE”打开脚本,按F5运行
delNum = 0
keepNum = 0
#函数shouldDel:若待某删类型的文件在字典里找不到对应快照,则返回True
def shouldDel(fileName, dictName, echoOn, countOn):
global delNum
global keepNum
portion = os.path.splitext(fileName)
if(fileToDel == portion[1]):#若后缀名是待删类型
fileToFind = portion[0]+fileToKeep #把后缀名换成快照类型
if fileToFind not in dictName.keys(): #若在字典里找不到该快照
if echoOn:
print ("待删除->> ", fileName)
if countOn:
delNum += 1
return True
else:
if echoOn:
print ("保留:", fileName)
if countOn:
keepNum += 1
return False
else:
return False
filePath = os.getcwd() #将脚本目录设为运行入口
fileToKeep = ".jpg" #快照类型
fileToDel = ".CR2" #待删类型
delDirName = "files to delete" #存放待删除文件的文件夹
print ("当前目录是", filePath)
delDirPath = os.path.join(filePath, delDirName)
if not os.path.exists(delDirPath):
print ("不存在[", delDirName, "]文件夹,创建")
os.makedirs(delDirPath)
else:
print('[',delDirName,']文件夹已存在')
#遍历并将所有文件名存入字典
dict1={ } #字典
for root, dirs, files in os.walk(filePath):
print("List: ",root)
dirFileNum = 0
for fName in files:
print("\t: "+ fName)
dirFileNum += 1
dict1[fName] = os.path.join(root, fName) #key:文件名;value:全路径
print ("共", dirFileNum, "个文件\n")
print ("-----------------------------------------------------------\n")
#方法一:重新遍历,根据字典判断是否要移动
for root, dirs, files in os.walk(filePath):
print("****处理Dir: ",root)
for fName in files:
notInDelDir = not(delDirPath == root)
if shouldDel(fName, dict1, True, notInDelDir):
if (notInDelDir):#如果不在待删除文件夹内
try:
shutil.move(dict1[fName], delDirPath)
except :
错误标题 = str( sys.exc_info()[0] );
错误细节 = str( sys.exc_info() );
print("遇到【" + 错误标题 + "】错误。细节:" + 错误细节);
else:
pass
else: #如果在待删除文件夹内,则什么也不做
pass
print ("共移动 ", delNum, "个文件")
print ("共保留",keepNum, "个文件\n\n")
#方法二:更高性能的遍历,但会乱序
''' for k,v in dict1.items(): #用字典固有的遍历方法重新遍历 '''
3.按使用说明运行脚本
- 把要整理的照片的raw文件以及本脚本放在一个文件夹内
- 用光影魔术手之类的格式转换软件把这些raw转换成jpg,放进一个子文件夹
- 用任意图片浏览器浏览jpg,删除不需要的照片
- 用python集成进鼠标右键的“Edit with IDLE”打开脚本,按F5运行
心得体会
- 要是已经太久没写脚本,将会:实际耗时 = (预计耗时 * 3) (:з」∠)
- python2对中文路径的支持不好,比如os.walk的值print出去是乱码,用unicode函数转换有时又会抛异常
- 文件名遍历进字典后会乱序,虽说用sorted函数可以对字典排序,但输出的是一个LIst,失去了用字典的意义
- 用shutil.move前要判断一下是不是src就在dst里,否则会抛异常
- 函数里用全局变量前要用global声明一下
- 函数的定义要写在使用前
- 无类型的基本变量类型的参数在python函数里是值传递,list、字典之类的带类型的参数在函数里是引用传递
- os.path.splitext()可以分离出文件后缀名
- os.path.basename(filePath)获取某路径的最后一级目录名
- os.path.join()可以用来生成文件的全路径名
- os.walk()可用来遍历文件夹内的所有文件
- try语句里的else分支表示无异常的情况