复制文件 usingwin32com.shell Windows 中的 pidl 参考 - 从 iPhone 复制图片文件
Copying files usingwin32com.shell pidl reference in Windows - to copy picture files off an iPhone
我一直在尝试找到一种从 iPhone 复制文件的方法,但是尽管能够使用 win32com.shell GetDisplayNameOf 和 BindToObject 列出其中的文件,但我似乎找不到仅使用 pidl 引用复制文件的任何方式。
不幸的是,当 iPhone 连接到 Windows 时,它不会安装为驱动器盘符,需要您使用 PIDL 引用而不是完整路径。然而,经过大量谷歌搜索,我似乎无法找到一种仅使用 PIDL 参考进行复制的方法。
"path = shell.SHGetPathFromIDList(pidl)" 似乎是从 PIDL 中查找文件系统路径的潜在选项,但是由于 iPhone 没有挂载到文件系统路径,因此给定 PIDL 值时总是 returns 出错。
到目前为止我使用的示例代码(取自How can I iterate across the photos on my connected iPhone from Windows 7 in Python?):
from win32com.shell import shell, shellcon
desktop = shell.SHGetDesktopFolder()
for pidl in desktop:
if desktop.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) == "This PC":
# path = shell.SHGetPathFromIDList(pidl)
print path
break
folder = desktop.BindToObject(pidl, None, shell.IID_IShellFolder)
for pidl in folder:
if folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) == "My iPhone":
break
folder = folder.BindToObject(pidl, None, shell.IID_IShellFolder)
for pidl in folder:
if folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) == "Internal Storage":
break
folder = folder.BindToObject(pidl, None, shell.IID_IShellFolder)
for pidl in folder:
if folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) == "DCIM":
break
# Each of the image folders
folder = folder.BindToObject(pidl, None, shell.IID_IShellFolder)
for pidl in folder:
# print folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL)
files = folder.BindToObject(pidl, None, shell.IID_IShellFolder)
for curfile in files:
current_file = folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) + "\" + files.GetDisplayNameOf(curfile, shellcon.SHGDN_NORMAL)
folder.BindToObject(pidl, )
有没有人有什么想法?
到目前为止我使用的主要参考资料:
使用 PIDL 正确读取文件系统的示例代码:How can I iterate across the photos on my connected iPhone from Windows 7 in Python?
如何从 iPhone 列出文件的示例,但没有关于如何复制它们的详细信息:https://github.com/dblume/list-photos-on-phone/blob/master/list-photos-on-phone.py
不太确定内容的链接。但是一旦我有了 PIDL,我就可以复制文件了。您必须创建文件和目标的 ShellItem。然后使用 IFileOperation。我认为这主要是大量谷歌搜索和查找微软 MSDN docs.
无论如何,这是代码。希望对您有所帮助!
from win32com.shell import shell, shellcon
import pythoncom
#fo is the folder IShellFolder object
#dsk is the destination IShellFolder object
#fi is the PIDL of the item you wish to copy (eg. the photo on your iPhone)
fidl = shell.SHGetIDListFromObject(fo) #Grab the PIDL from the folder object
didl = shell.SHGetIDListFromObject(dsk) #Grab the PIDL from the folder object
si = shell.SHCreateShellItem(fidl, None, fi) #Create a ShellItem of the source file
dst = shell.SHCreateItemFromIDList(didl)
#Python IFileOperation
pfo = pythoncom.CoCreateInstance(shell.CLSID_FileOperation,None,pythoncom.CLSCTX_ALL,shell.IID_IFileOperation)
pfo.SetOperationFlags(shellcon.FOF_NOCONFIRMATION)
pfo.CopyItem(si, dst, "Destination Name.jpg") # Schedule an operation to be performed
success = pfo.PerformOperations() #perform operation
祝你项目顺利!
感谢以上信息,有了这些信息,我能够实现 python 将照片从 iPhone X 移动到 Windows10 PC。以下主要功能
# imports probably needed
from win32com.shell import shell, shellcon
from win32com.propsys import propsys
import pythoncom
# Recursive function to browse into a non filesystem path
def recurse_and_get_ishellfolder(base_ishellfolder, path):
splitted_path = path.split("\", 1)
for pidl in base_ishellfolder:
if base_ishellfolder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) == splitted_path[0]:
break
folder = base_ishellfolder.BindToObject(pidl, None, shell.IID_IShellFolder)
if len(splitted_path) > 1:
# More to recurse
return recurse_and_get_ishellfolder(folder, splitted_path[1])
else:
return folder
# How to move non filesystem file to filesystem patj
def move_file_by_pidl_to_path(src_ishellfolder, src_pidl, dst_path, dst_filename):
pidl_folder_dst, flags = shell.SHILCreateFromPath(dst_path, 0)
dst_ishellfolder = shell.SHGetDesktopFolder().BindToObject(pidl_folder_dst, None, shell.IID_IShellFolder)
fidl = shell.SHGetIDListFromObject(src_ishellfolder) # Grab the PIDL from the folder object
didl = shell.SHGetIDListFromObject(dst_ishellfolder) # Grab the PIDL from the folder object
si = shell.SHCreateShellItem(fidl, None, src_pidl) # Create a ShellItem of the source file
dst = shell.SHCreateItemFromIDList(didl)
pfo = pythoncom.CoCreateInstance(shell.CLSID_FileOperation, None, pythoncom.CLSCTX_ALL, shell.IID_IFileOperation)
pfo.SetOperationFlags(shellcon.FOF_NOCONFIRMATION | shellcon.FOF_SILENT | shellcon.FOF_NOERRORUI)
pfo.MoveItem(si, dst, dst_filename) # Schedule an operation to be performed
pfo.PerformOperations()
return not pfo.GetAnyOperationsAborted()
# Bonus: get file modification datetime for a non filesystem file
DATE_PROP_KEY = propsys.PSGetPropertyKeyFromName("System.DateModified")
DATE_PROP_PARSE_STR = '%Y/%m/%d:%H:%M:%S.%f' # not sure bout the f modifier but it does not really matter
def getmodified_datetime_by_pidl(src_ishellfolder, src_pidl):
fidl = shell.SHGetIDListFromObject(src_ishellfolder) # Grab the PIDL from the folder object
si = shell.SHCreateShellItem(fidl, None, src_pidl) # Create a ShellItem of the source file
ps = propsys.PSGetItemPropertyHandler(si)
date_str = ps.GetValue(DATE_PROP_KEY).ToString()
return datetime.strptime(date_str, DATE_PROP_PARSE_STR)
# Example photo moving main logic
def move_files():
main_folder = recurse_and_get_ishellfolder(shell.SHGetDesktopFolder(), "This Pc\path\to\DCIM")
for photo_folder_pidl in main_folder:
folder_name = main_folder.GetDisplayNameOf(photo_folder_pidl, shellcon.SHGDN_NORMAL)
folder = main_folder.BindToObject(photo_folder_pidl, None, shell.IID_IShellFolder)
for pidl in folder:
child_name = folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL)
file_mod_date = getmodified_datetime_by_pidl(folder, pidl)
if not older_than_datetime or file_mod_date < older_than_datetime:
print("Transferring file: " + child_name)
move_file_by_pidl_to_path(...)
else:
print("Skipping too recent file: " + child_name)
移动照片的完整脚本:
https://gitlab.com/lassi.niemisto/iphone-photo-dump
编辑:链接实现的关键部分作为代码复制到此处
我一直在尝试找到一种从 iPhone 复制文件的方法,但是尽管能够使用 win32com.shell GetDisplayNameOf 和 BindToObject 列出其中的文件,但我似乎找不到仅使用 pidl 引用复制文件的任何方式。
不幸的是,当 iPhone 连接到 Windows 时,它不会安装为驱动器盘符,需要您使用 PIDL 引用而不是完整路径。然而,经过大量谷歌搜索,我似乎无法找到一种仅使用 PIDL 参考进行复制的方法。
"path = shell.SHGetPathFromIDList(pidl)" 似乎是从 PIDL 中查找文件系统路径的潜在选项,但是由于 iPhone 没有挂载到文件系统路径,因此给定 PIDL 值时总是 returns 出错。
到目前为止我使用的示例代码(取自How can I iterate across the photos on my connected iPhone from Windows 7 in Python?):
from win32com.shell import shell, shellcon
desktop = shell.SHGetDesktopFolder()
for pidl in desktop:
if desktop.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) == "This PC":
# path = shell.SHGetPathFromIDList(pidl)
print path
break
folder = desktop.BindToObject(pidl, None, shell.IID_IShellFolder)
for pidl in folder:
if folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) == "My iPhone":
break
folder = folder.BindToObject(pidl, None, shell.IID_IShellFolder)
for pidl in folder:
if folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) == "Internal Storage":
break
folder = folder.BindToObject(pidl, None, shell.IID_IShellFolder)
for pidl in folder:
if folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) == "DCIM":
break
# Each of the image folders
folder = folder.BindToObject(pidl, None, shell.IID_IShellFolder)
for pidl in folder:
# print folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL)
files = folder.BindToObject(pidl, None, shell.IID_IShellFolder)
for curfile in files:
current_file = folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) + "\" + files.GetDisplayNameOf(curfile, shellcon.SHGDN_NORMAL)
folder.BindToObject(pidl, )
有没有人有什么想法?
到目前为止我使用的主要参考资料: 使用 PIDL 正确读取文件系统的示例代码:How can I iterate across the photos on my connected iPhone from Windows 7 in Python?
如何从 iPhone 列出文件的示例,但没有关于如何复制它们的详细信息:https://github.com/dblume/list-photos-on-phone/blob/master/list-photos-on-phone.py
不太确定内容的链接。但是一旦我有了 PIDL,我就可以复制文件了。您必须创建文件和目标的 ShellItem。然后使用 IFileOperation。我认为这主要是大量谷歌搜索和查找微软 MSDN docs.
无论如何,这是代码。希望对您有所帮助!
from win32com.shell import shell, shellcon
import pythoncom
#fo is the folder IShellFolder object
#dsk is the destination IShellFolder object
#fi is the PIDL of the item you wish to copy (eg. the photo on your iPhone)
fidl = shell.SHGetIDListFromObject(fo) #Grab the PIDL from the folder object
didl = shell.SHGetIDListFromObject(dsk) #Grab the PIDL from the folder object
si = shell.SHCreateShellItem(fidl, None, fi) #Create a ShellItem of the source file
dst = shell.SHCreateItemFromIDList(didl)
#Python IFileOperation
pfo = pythoncom.CoCreateInstance(shell.CLSID_FileOperation,None,pythoncom.CLSCTX_ALL,shell.IID_IFileOperation)
pfo.SetOperationFlags(shellcon.FOF_NOCONFIRMATION)
pfo.CopyItem(si, dst, "Destination Name.jpg") # Schedule an operation to be performed
success = pfo.PerformOperations() #perform operation
祝你项目顺利!
感谢以上信息,有了这些信息,我能够实现 python 将照片从 iPhone X 移动到 Windows10 PC。以下主要功能
# imports probably needed
from win32com.shell import shell, shellcon
from win32com.propsys import propsys
import pythoncom
# Recursive function to browse into a non filesystem path
def recurse_and_get_ishellfolder(base_ishellfolder, path):
splitted_path = path.split("\", 1)
for pidl in base_ishellfolder:
if base_ishellfolder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL) == splitted_path[0]:
break
folder = base_ishellfolder.BindToObject(pidl, None, shell.IID_IShellFolder)
if len(splitted_path) > 1:
# More to recurse
return recurse_and_get_ishellfolder(folder, splitted_path[1])
else:
return folder
# How to move non filesystem file to filesystem patj
def move_file_by_pidl_to_path(src_ishellfolder, src_pidl, dst_path, dst_filename):
pidl_folder_dst, flags = shell.SHILCreateFromPath(dst_path, 0)
dst_ishellfolder = shell.SHGetDesktopFolder().BindToObject(pidl_folder_dst, None, shell.IID_IShellFolder)
fidl = shell.SHGetIDListFromObject(src_ishellfolder) # Grab the PIDL from the folder object
didl = shell.SHGetIDListFromObject(dst_ishellfolder) # Grab the PIDL from the folder object
si = shell.SHCreateShellItem(fidl, None, src_pidl) # Create a ShellItem of the source file
dst = shell.SHCreateItemFromIDList(didl)
pfo = pythoncom.CoCreateInstance(shell.CLSID_FileOperation, None, pythoncom.CLSCTX_ALL, shell.IID_IFileOperation)
pfo.SetOperationFlags(shellcon.FOF_NOCONFIRMATION | shellcon.FOF_SILENT | shellcon.FOF_NOERRORUI)
pfo.MoveItem(si, dst, dst_filename) # Schedule an operation to be performed
pfo.PerformOperations()
return not pfo.GetAnyOperationsAborted()
# Bonus: get file modification datetime for a non filesystem file
DATE_PROP_KEY = propsys.PSGetPropertyKeyFromName("System.DateModified")
DATE_PROP_PARSE_STR = '%Y/%m/%d:%H:%M:%S.%f' # not sure bout the f modifier but it does not really matter
def getmodified_datetime_by_pidl(src_ishellfolder, src_pidl):
fidl = shell.SHGetIDListFromObject(src_ishellfolder) # Grab the PIDL from the folder object
si = shell.SHCreateShellItem(fidl, None, src_pidl) # Create a ShellItem of the source file
ps = propsys.PSGetItemPropertyHandler(si)
date_str = ps.GetValue(DATE_PROP_KEY).ToString()
return datetime.strptime(date_str, DATE_PROP_PARSE_STR)
# Example photo moving main logic
def move_files():
main_folder = recurse_and_get_ishellfolder(shell.SHGetDesktopFolder(), "This Pc\path\to\DCIM")
for photo_folder_pidl in main_folder:
folder_name = main_folder.GetDisplayNameOf(photo_folder_pidl, shellcon.SHGDN_NORMAL)
folder = main_folder.BindToObject(photo_folder_pidl, None, shell.IID_IShellFolder)
for pidl in folder:
child_name = folder.GetDisplayNameOf(pidl, shellcon.SHGDN_NORMAL)
file_mod_date = getmodified_datetime_by_pidl(folder, pidl)
if not older_than_datetime or file_mod_date < older_than_datetime:
print("Transferring file: " + child_name)
move_file_by_pidl_to_path(...)
else:
print("Skipping too recent file: " + child_name)
移动照片的完整脚本: https://gitlab.com/lassi.niemisto/iphone-photo-dump
编辑:链接实现的关键部分作为代码复制到此处