Board logo

标题: [问题求助] [已解决]PowerShell搜索佳能EOS M2微单相机文件并复制到本地硬盘 [打印本页]

作者: ygqiang    时间: 2016-3-12 07:54     标题: [已解决]PowerShell搜索佳能EOS M2微单相机文件并复制到本地硬盘

佳能EOS M2微单相机,usb数据线连接win7系统。powershell代码问题请教。

powershell代码功能是:搜索相机里面的照片、视频文件,并复制到本地d盘下的日期文件夹下(比如2016-03)。
佳能微单相机,用usb数据线连上win7 64系统,运行powershell代码,发现的规律是:
1、如果先通过鼠标手动点开相机的照片目录。
第1次运行代码,代码就能复制相机里的全部照片/视频到本地硬盘了。
2、如果不通过鼠标手动点开相机的照片目录。要反复运行2-4次代码,代码才能复制全部照片/视频到本地硬盘。


遇到的问题是:相机与win7 64系统usb数据线连接,
1、第1次运行代码,只复制了10张照片。
手动删除图片目录d:\2016-03(代码在d盘新建的)
2、第2次运行代码,只复制了15张照片。
手动删除图片目录d:\2016-03
3、第3次运行代码,才复制了全部照片21张。

然后断开usb连接,重新连接usb数据线。如果用鼠标手动点击开相机里的照片/视频目录。
1、第1次运行代码,复制了全部照片21张。
手动删除图片目录d:\2016-03
2、第2次运行代码,复制了全部照片21张。
作者: ygqiang    时间: 2016-3-12 07:59

相机usb数据线连接win7系统,截图。。
作者: ygqiang    时间: 2016-3-12 08:01

powershell代码如下。如何修改呢?多谢
  1. #
  2. # 获取 Shell.Application 代理
  3. #  
  4. function Get-ShellProxy
  5. {
  6.   if( -not $global:ShellProxy) {  
  7.   $global:ShellProxy = new-object -com Shell.Application
  8.   }
  9.   $global:ShellProxy
  10. }
  11. #
  12. # 查看 Shell 项
  13. #  
  14. function Get-ShellItem
  15. {
  16. param($Path=17)
  17. $shell=Get-ShellProxy
  18. # 默认的 NameSpace()方法只支持目录,不支持文件
  19. # 为了增强兼容性和保持一致性,如果传入一个文件路径,可以尝试通过文件路径获取目录,然后再从目录的子项中获取Shell项
  20. trap [System.Management.Automation.MethodInvocationException]
  21. {
  22.   $Path = $Path.ToString()
  23.   $dir = $Path.Substring( 0 ,$Path.LastIndexOf('\') )
  24.   return $shell.NameSpace($dir).items()  |  
  25.    where { (-not $_.IsFolder ) -and  $_.path -eq $Path} |
  26.    select -First 1
  27.   continue
  28. }
  29. $shell.NameSpace($Path).self
  30. }
  31. #
  32. # 查看 Shell 子项,支持递归和过滤
  33. #  
  34. function Get-ChildShellItem
  35. {
  36. param(
  37.   $Path=17,
  38.   [switch]$Recurse,
  39.   $Filter=$null)
  40. #内部过滤器
  41. Filter myFilter
  42. {
  43.    if($Filter){
  44.    $_ | where { $_.Name -match $Filter }
  45.    }
  46.    else{
  47.    $_
  48.    }
  49. }
  50. $shellItem = Get-ShellItem $Path
  51. $shellItem | myFilter
  52. # 如果是目录
  53. if( $shellItem.IsFolder ){  
  54.   # 如果指定递归
  55.   if($Recurse) {
  56.    $shellItem | myFilter
  57.    $stack=New-Object System.Collections.Stack
  58.    # 当前目录压入堆栈
  59.    $stack.Push($shellItem)
  60.    while($stack.Count -gt 0)
  61.    {
  62.      # 访问栈顶元素
  63.      $top = $stack.Pop()
  64.      $top | myFilter
  65.      # 访问栈顶元素的子元素
  66.      $top.GetFolder.items() | foreach {
  67.        if( $_.IsFolder )
  68.        { $stack.Push($_) }
  69.        else { $_ | myFilter }
  70.      }
  71.    }
  72.   }
  73.   else{
  74.   $shellItem.GetFolder.items() | myFilter }
  75.   }
  76. }
  77. #
  78. # 复制Shell项
  79. #
  80. function Copy-ShellItem
  81. {
  82. param($Path,$Destination)
  83. $shell=Get-ShellProxy
  84. $shell.NameSpace($Destination).Copyhere($Path,4)
  85. }
  86. #
  87. # 删除Shell项
  88. #
  89. function Remove-ShellItem
  90. {
  91. param($Path)
  92. $ShellItem = Get-ShellItem $Path
  93. $ShellItem.InvokeVerb('delete')
  94. }
  95. #
  96. # 移动Shell项
  97. #
  98. function Move-ShellItem
  99. {
  100. param($Path,$Destination)
  101. $shell=Get-ShellProxy
  102. $shell.NameSpace($Destination).MoveHere($Path,16)
  103. }
  104. # 文件存放的地址
  105. $des = 'd:\'
  106. # 匹配相机的关键字,比如:canon,nokia,Windows Phone,meizu,Smartisan,ZUK Z1
  107. $keywords = 'canon','meizu','Windows Phone','nokia','Smartisan','ZUK Z1'
  108. foreach ($keyword in $keywords)
  109. {
  110. $phones = Get-ChildShellItem | where { $_.name -like "*$keyword*" }
  111. foreach ($phone in $phones)
  112. {
  113. if($phone -eq $null)
  114. {
  115. break
  116. }
  117. Get-ChildShellItem -Path "$($phone.Path)" -Recurse -Filter '((.jpg)|(.crw)|(.cr2)|(.avi)|(.mov)|(.mp4))$' | foreach {
  118. #获取照片创建日期
  119. $datestr = $_.Parent.GetDetailsOf($_,3)
  120. $datestr=(get-date).tostring("yyyy-MM")
  121. #新建日期文件夹
  122. $dir = Join-Path $des $datestr
  123. if( -not (Test-Path $dir) ) {
  124. mkdir $dir
  125. }
  126. # 如果文件存在,先删掉
  127. $file="{0}\{1}" -f $dir,$_.name
  128. if( test-path $file) {  remove-item $file }
  129. # 复制文件
  130. Copy-ShellItem -Path $_ -Destination $dir
  131. # 移动文件
  132. # move-ShellItem -Path $_ -Destination $dir
  133. }
  134. }
  135. }
  136. exit
  137. $des =  [environment]::GetFolderPath([System.Environment+SpecialFolder]::MyPictures)
复制代码

作者: 523066680    时间: 2016-3-12 09:06

这……  你有LOFTER账号吗,交流
作者: ivor    时间: 2016-3-12 11:06

回复 3# ygqiang


    应该不是代码的问题,可能是系统读取相机图片错误
作者: ygqiang    时间: 2016-3-12 12:48

本帖最后由 ygqiang 于 2016-3-12 12:53 编辑

回复 5# ivor


    应该不是。
为啥多运行几次,就会全部复制出来呢?

有人说:
先将相机里面的照片/视频列表出来,先ls一下相机卡目录,
再拷贝,就可以了。
作者: ivor    时间: 2016-3-12 12:50

回复 6# ygqiang


    先调试能否获取到完整的全部文件列表
作者: ygqiang    时间: 2016-3-12 13:52

回复 7# ivor


    对powershell代码不懂啊。能否帮忙修改下。谢谢了
作者: ivor    时间: 2016-3-12 13:53

本帖最后由 ivor 于 2016-3-12 18:30 编辑

回复 1# ygqiang


    我用Python写的,放在相机最顶层
  1. # coding:utf-8
  2. # python 3.5.1
  3. import os, shutil, time
  4. # 需要复制的文件名后缀数组
  5. end_filter = ('.jpg','.crw', '.cr2', '.avi','.mov', '.mp4')
  6. # 目标文件夹
  7. dest_dir = 'd:\\%s-%s'% (time.localtime().tm_year,time.localtime().tm_mon)
  8. # 如果目标文件不存在则创建
  9. if os.path.exists(dest_dir) == False:
  10.     os.mkdir(dest_dir)
  11. # 遍历查找需要复制的文件
  12. for parent, dirnames, files in os.walk('.'):
  13.     for i in files:
  14.         if i.endswith(end_filter):
  15.             shutil.copy(('%s\\%s'% (parent, i)),dest_dir)
  16.             print('copying %s\\%s'% (parent, i))
  17. os.system('pause')
  18.             
复制代码

作者: ygqiang    时间: 2016-3-12 17:01

回复 9# ivor


    用Python写的,放在相机最顶层???

具体如何使用呢?
台式机win7系统环境下,都需要装什么软件?多谢
作者: ivor    时间: 2016-3-12 17:22

回复 10# ygqiang


    https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe  

代码保存为xx.py,后缀是.py,放在相机里面运行就会复制当前目录下面所有的照片和视频到指定目录
作者: ygqiang    时间: 2016-3-12 18:19

本帖最后由 ygqiang 于 2016-3-12 18:22 编辑

回复 11# ivor


    多谢。一会测试下啊。
请问下,
# 遍历查找需要复制的文件
这个下面的代码,哪里体现出搜索佳能微单EOS M2目录下的图片/视频文件了呢?


还有,能否修改成:根据当前的年和月份,如果检测到d盘下面没有这种目录,就自动建立目录。
比如2016-03、2016-10、2017-01等等,
作者: ygqiang    时间: 2016-3-12 18:26

回复 11# ivor


    文件复制不到相机任何一个目录下。
作者: ygqiang    时间: 2016-3-12 18:27

回复 11# ivor


    xx.py最好放在d盘根目录下,运行1次,就自动搜索相机目录并复制所有照片/视频,到d盘的某个时间/日期目录下。
作者: ygqiang    时间: 2016-3-12 18:35

本帖最后由 ygqiang 于 2016-3-12 18:36 编辑

回复 9# ivor


    你的py代码测试了。
如果py文件放在普通的目录下,目录下有01.jpg,02.jpg,IMG_0296.JPG,IMG_0298.JPG等等照片
运行py代码,只能复制01和02照片,IMG_xxxx.jpg的照片,无法复制。

搞定了。竟然也分辨大小写的扩展名。

end_filter = ('.jpg','.JPG','.crw', '.cr2', '.avi','.mov', '.mp4')
作者: ygqiang    时间: 2016-3-12 18:59

回复 11# ivor


    你的这个py代码。bat批处理也能实现。
  1. echo 搜索某个目录下所有的jpg文件,并复制到目标目录
  2. setlocal enabledelayedexpansion&for /f "delims=" %%a in ('dir /s /b C:\000\*.jpg') do (copy "%%a" "D:\test")
复制代码

作者: ivor    时间: 2016-3-12 19:13

回复 16# ygqiang


    我搜了一下,访问相机好像很麻烦
作者: ygqiang    时间: 2016-3-12 19:18

回复 17# ivor


相机/手机,通过usb数据线连接到win7系统,不显示U盘那种盘符。
    访问/读取这种设备,应该有统一的解决方案吧?
作者: ygqiang    时间: 2016-3-12 22:40

初步解决了。索引文件需要些时间 等待一会的话 文件就全了。
  1. #
  2. # 获取 Shell.Application 代理
  3. #  
  4. function Get-ShellProxy
  5. {
  6.   if( -not $global:ShellProxy) {  
  7.   $global:ShellProxy = new-object -com Shell.Application
  8.   }
  9.   $global:ShellProxy
  10. }
  11. #
  12. # 查看 Shell 项
  13. #  
  14. function Get-ShellItem
  15. {
  16. param($Path=17)
  17. $shell=Get-ShellProxy
  18. # 默认的 NameSpace()方法只支持目录,不支持文件
  19. # 为了增强兼容性和保持一致性,如果传入一个文件路径,可以尝试通过文件路径获取目录,然后再从目录的子项中获取Shell项
  20. trap [System.Management.Automation.MethodInvocationException]
  21. {
  22.   $Path = $Path.ToString()
  23.   $dir = $Path.Substring( 0 ,$Path.LastIndexOf('\') )
  24.   return $shell.NameSpace($dir).items()  |  
  25.    where { (-not $_.IsFolder ) -and  $_.path -eq $Path} |
  26.    select -First 1
  27.   continue
  28. }
  29. $shell.NameSpace($Path).self
  30. }
  31. #
  32. # 查看 Shell 子项,支持递归和过滤
  33. #  
  34. function Get-ChildShellItem
  35. {
  36. param(
  37.   $Path=17,
  38.   [switch]$Recurse,
  39.   $Filter=$null)
  40. #内部过滤器
  41. Filter myFilter
  42. {
  43.    if($Filter){
  44.    $_ | where { $_.Name -match $Filter }
  45.    }
  46.    else{
  47.    $_
  48.    }
  49. }
  50. $shellItem = Get-ShellItem $Path
  51. $shellItem | myFilter
  52. # 如果是目录
  53. if( $shellItem.IsFolder ){  
  54.   # 如果指定递归
  55.   if($Recurse) {
  56.    $shellItem | myFilter
  57.    $stack=New-Object System.Collections.Stack
  58.    # 当前目录压入堆栈
  59.    $stack.Push($shellItem)
  60.    while($stack.Count -gt 0)
  61.    {
  62.      # 访问栈顶元素
  63.      $top = $stack.Pop()
  64.      $top | myFilter
  65.      # 访问栈顶元素的子元素
  66.      $top.GetFolder.items() | foreach {
  67.        if( $_.IsFolder )
  68.        { $stack.Push($_) }
  69.        else { $_ | myFilter }
  70.      }
  71.    }
  72.   }
  73.   else{
  74.   $shellItem.GetFolder.items() | myFilter }
  75.   }
  76. }
  77. #
  78. # 复制Shell项
  79. #
  80. function Copy-ShellItem
  81. {
  82. param($Path,$Destination)
  83. $shell=Get-ShellProxy
  84. $shell.NameSpace($Destination).Copyhere($Path,4)
  85. }
  86. #
  87. # 删除Shell项
  88. #
  89. function Remove-ShellItem
  90. {
  91. param($Path)
  92. $ShellItem = Get-ShellItem $Path
  93. $ShellItem.InvokeVerb('delete')
  94. }
  95. #
  96. # 移动Shell项
  97. #
  98. function Move-ShellItem
  99. {
  100. param($Path,$Destination)
  101. $shell=Get-ShellProxy
  102. $shell.NameSpace($Destination).MoveHere($Path,16)
  103. }
  104. # 文件存放的地址
  105. $des = 'd:\'
  106. # 匹配相机的关键字,比如:canon,nokia,Windows Phone,meizu,Smartisan,ZUK Z1
  107. $keywords = 'canon','meizu','Windows Phone','nokia','Smartisan','ZUK Z1'
  108. foreach ($keyword in $keywords)
  109. {
  110. $phones = Get-ChildShellItem | where { $_.name -like "*$keyword*" }
  111. foreach ($phone in $phones)
  112. {
  113. if($phone -eq $null)
  114. {
  115. break
  116. }
  117. 1..3|%{Get-ChildShellItem -Path "$($phone.Path)" -Recurse -Filter '((.jpg)|(.crw)|(.cr2)|(.avi)|(.mov)|(.mp4))$'
  118. sleep 3}
  119. Get-ChildShellItem -Path "$($phone.Path)" -Recurse -Filter '((.jpg)|(.crw)|(.cr2)|(.avi)|(.mov)|(.mp4))$'| foreach {
  120. #获取照片创建日期
  121. $datestr = $_.Parent.GetDetailsOf($_,3)
  122. $datestr=(get-date).tostring("yyyy-MM")
  123. #新建日期文件夹
  124. $dir = Join-Path $des $datestr
  125. if( -not (Test-Path $dir) ) {
  126. mkdir $dir
  127. }
  128. # 如果文件存在,先删掉
  129. $file="{0}\{1}" -f $dir,$_.name
  130. if( test-path $file) {  remove-item $file }
  131. # 复制文件
  132. Copy-ShellItem -Path $_ -Destination $dir
  133. # 移动文件
  134. # move-ShellItem -Path $_ -Destination $dir
  135. }
  136. }
  137. }
  138. exit
  139. $des =  [environment]::GetFolderPath([System.Environment+SpecialFolder]::MyPictures)
复制代码





欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2