Python 如何用Python将手机内的文件(照片)批量导入电脑,并增加文件创建日期
前言
随着手机内照片数量越来越多,手机内存储空间不够,就需要将手机内的照片或文件拷贝到电脑上,这种有很多第三方软件可以实现,但是又不想使用第三方软件,于是就试着用python实现文件或照片备份的目的,这里记录下如何实现批量拷贝手机内的文件到电脑上,给有需要的朋友提供思路。
一、拷贝文件的探索
最先想到的就是通过os库遍历文件后,用shutil库进行文件的拷贝,等到真正实现的时候发现,手机连接到电脑上后能看到手机文件夹的路径,用鼠标也能操作复制,但是如果想用os库遍历文件时会发现无法找到路径或路径不存在,根本没法遍历,所以也就没法复制,也试了其他很多库都是无法找到路径,最后只能用其他办法实现 。
二、shell接口
最后通过查找资料,发现shell接口可以实现此功能,这里记录下基本的操作
1.通过shell获取需要复制的文件夹对象,以下为具体代码,原理是通过遍历文件夹,通过比对找到所需复制的文件夹对象,path为需要复制的手机文件夹路径,如:path=r’此电脑\Apple iPhone\Internal Storage\DCIM’
def get_folder(path,folder=None):
folder_name = path.split("\\", 1)
base_folder = folder or shell.SHGetDesktopFolder()
for pidl in base_folder:
if base_folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) == folder_name[0]:
folder = base_folder.BindToObject(pidl, None, shell.IID_IShellFolder)
break
if len(folder_name) > 1:
return get_folder(folder_name[1],folder)
else:
return folder
2.遍历此文件夹下的所有文件和文件夹,然后拷贝到电脑上即可,同时可读取文件创建日期,方便后面将文件创建日期增加到文件名上,查看文件创建日期,因为照片拷贝到电脑后创建日期将会被修改,后期想查看创建日期就看不到原始日期了,所以可以将此日期增加的文件名上,也可以将文件创建日期进行修改,但个人觉得没有修改文件名直观,以下为具体代码
def copy_files_to_computer(folder,phonefolderpath,computerdir,current_computer_dir=None,date_name=True):
if folder:
is_pfo=True
# 遍历文件
for file_pidl in folder:
# 获取文件名
file_name = folder.GetDisplayNameOf(file_pidl, shellcon.SHGDN_FORADDRESSBAR)
# 判断是否为文件夹
is_folder=folder.GetAttributesOf([file_pidl],shellcon.SFGAO_FOLDER)
if is_folder==536870912:
#生成电脑文件夹路径,将手机路径替换为电脑路径
new_computerdir=file_name.replace(phonefolderpath,computerdir)
# 如果电脑不存在文件夹则新建文件夹
if not os.path.exists(new_computerdir):
os.makedirs(new_computerdir)
new_folder = folder.BindToObject(file_pidl, None, shell.IID_IShellFolder)
copy_files_to_computer(new_folder,phonefolderpath,computerdir,new_computerdir)
# 如果是文件,则进行拷贝
elif is_folder==0:
if current_computer_dir is not None:
computerdirpidl,_=shell.SHILCreateFromPath(current_computer_dir, 0)
else:
computerdirpidl,_=shell.SHILCreateFromPath(computerdir, 0)
computerdiritem = shell.SHCreateItemFromIDList(computerdirpidl)
phonefolderpidl = shell.SHGetIDListFromObject(folder)
# 生成当前复制的文件的PIDL,手机文件夹的PIDL+文件的PIDL
filepidl=phonefolderpidl+file_pidl
pidlitem = shell.SHCreateItemFromIDList(filepidl,shell.IID_IShellItem2)
# 创建com对象
pfo = pythoncom.CoCreateInstance(shell.CLSID_FileOperation, None, pythoncom.CLSCTX_ALL, shell.IID_IFileOperation)
pfo.SetOperationFlags(shellcon.FOF_NOCONFIRMATION | shellcon.FOF_SILENT | shellcon.FOF_NOERRORUI)
# 是否给文件名增加日期前缀
new_file_name=None
if date_name:
new_file_name=f'{
pidlitem.GetFileTime(("{EF6B490D-5CD8-437A-AFFC-DA8B60EE4A3C}", 19)).Format("%Y-%m-%d %H-%M-%S")}@{
pidlitem.GetDisplayName(shellcon.SHGDN_NORMAL)}'
# 拷贝文件
pfo.CopyItem(pidlitem, computerdiritem,new_file_name) # Schedule an operation to be performed
pfo.PerformOperations()
三、完成代码
from win32com.shell import shell, shellcon
import os
import pythoncom
def get_folder(path,folder=None):
folder_name = path.split("\\", 1)
base_folder = folder or shell.SHGetDesktopFolder()
for pidl in base_folder:
if base_folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) == folder_name[0]:
folder = base_folder.BindToObject(pidl, None, shell.IID_IShellFolder)
break
if len(folder_name) > 1:
return get_folder(folder_name[1],folder)
else:
return folder
def copy_files_to_computer(folder,phonefolderpath,computerdir,current_computer_dir=None,date_name=True):
if folder:
is_pfo=True
# 遍历文件
for file_pidl in folder:
# 获取文件名
file_name = folder.GetDisplayNameOf(file_pidl, shellcon.SHGDN_FORADDRESSBAR)
# 判断是否为文件夹
is_folder=folder.GetAttributesOf([file_pidl],shellcon.SFGAO_FOLDER)
if is_folder==536870912:
#生成电脑文件夹路径,将手机路径替换为电脑路径
new_computerdir=file_name.replace(phonefolderpath,computerdir)
# 如果电脑不存在文件夹则新建文件夹
if not os.path.exists(new_computerdir):
os.makedirs(new_computerdir)
new_folder = folder.BindToObject(file_pidl, None, shell.IID_IShellFolder)
copy_files_to_computer(new_folder,phonefolderpath,computerdir,new_computerdir)
# 如果是文件,则进行拷贝
elif is_folder==0:
if current_computer_dir is not None:
computerdirpidl,_=shell.SHILCreateFromPath(current_computer_dir, 0)
else:
computerdirpidl,_=shell.SHILCreateFromPath(computerdir, 0)
computerdiritem = shell.SHCreateItemFromIDList(computerdirpidl)
phonefolderpidl = shell.SHGetIDListFromObject(folder)
# 生成当前复制的文件的PIDL,手机文件夹的PIDL+文件的PIDL
filepidl=phonefolderpidl+file_pidl
pidlitem = shell.SHCreateItemFromIDList(filepidl,shell.IID_IShellItem2)
# 创建com对象
pfo = pythoncom.CoCreateInstance(shell.CLSID_FileOperation, None, pythoncom.CLSCTX_ALL, shell.IID_IFileOperation)
pfo.SetOperationFlags(shellcon.FOF_NOCONFIRMATION | shellcon.FOF_SILENT | shellcon.FOF_NOERRORUI)
# 是否给文件名增加日期前缀
new_file_name=None
if date_name:
new_file_name=f'{
pidlitem.GetFileTime(("{EF6B490D-5CD8-437A-AFFC-DA8B60EE4A3C}", 19)).Format("%Y-%m-%d %H-%M-%S")}@{
pidlitem.GetDisplayName(shellcon.SHGDN_NORMAL)}'
# 拷贝文件
pfo.CopyItem(pidlitem, computerdiritem,new_file_name) # Schedule an operation to be performed
pfo.PerformOperations()
if __name__ == '__main__':
phonepath=r'此电脑\Apple iPhone\Internal Storage\DCI'
computerdir=r'F:\test'
date_name=True
folder=get_folder(phonepath)
copy_files_to_computer(folder,phonepath,computerdir,date_name=date_name)
四、总结
以上代码实现了文件的遍历拷贝的基本流程,并未对拷贝过程中可能遇到的意外情况进行监控,如需监控需自定义实现FileOperationProgressSink类中的各种方法进行,同时此方法是会覆盖同名文件的并不会提示,如需提示可以设置此函数SetOperationFlags的相关参数,帮助中都能直接查到,很简单。