Welcome to my new blog! I wanted my first blog post to be something wholly positive, so I decided to share this Powershell script, in case there is anyone else out there who has struggled with automating the copying or moving of files from their phone. I find I am regularly cleaning pictures and other files off of my phone, due to the limited space, and for a long time I have wanted to make this process simpler and quicker – a one-click process would be ideal.
After searching online, I discovered this script, but from this page where there is a complaint that this script doesn’t work. Finding the same problem, I was able to use the provided Powershell and come up with a solution that does the job.
The problem with the script appeared to be in the Get-ChildShellItem function. The usage explanation in the page says to do the following:
$phone = Get-ChildShellItem | where { $_.name -eq 'a820t' } Get-ChildShellItem -Path "$($phone.Path)\Phone\DCIM" -Filter '(.jpg)|(.3gp)$'
This just causes the script to hang. The problem seems to be that even though the Path to the phone can be retrieved, Windows cannot use it to access the folder.
My solution is to get the phone object, then split the path and step down the tree, using the GetFolder member of each item, until we reach the folder object in question. See the functions, “Get-Phone” and “Get-SubFolder” respectively.
The next problem was how to move the files. The original script uses the “MoveHere” shell method, passing the path of the source file. Again, this doesn’t work because Windows doesn’t like the path of the MTP device. But looking at Microsoft’s website, I noticed that you can pass the folder item (the file COM object) directly. I do not know if this is the best way to do this (e.g. it can cause a file-copy dialogue to appear), but it works!
So, with that short explanation, here is an example MoveFromPhone.ps1 script. An example of how to use it (with a command script) is also included below.
This Powershell script is provided ‘as-is’, without any express or implied warranty. In no event will I, the author, be held liable for any damages arising from the use of this script.
Please note again, that if used ‘as-is’, this script will move files from you phone: they will be deleted from the source (phone) and moved to the computer. If you want to copy files instead, you can replace the “MoveHere” function call with “CopyHere” instead. But once again, I can take no responsibility for the use, or misuse, of this script.
# Windows Powershell Script to move a set of files (based on a filter) from a folder # on a MTP device (e.g. Android phone) to a folder on a computer, using the Windows Shell. # By Daiyan Yingyu, 19 March 2018, based on the (non-working) script found here: # https://www.pstips.net/access-file-system-against-mtp-connection.html # as referenced here: # https://powershell.org/forums/topic/powershell-mtp-connections/ # # This Powershell script is provided 'as-is', without any express or implied warranty. # In no event will the author be held liable for any damages arising from the use of this script. # # Again, please note that used 'as-is' this script will MOVE files from you phone: # the files will be DELETED from the source (the phone) and MOVED to the computer. # # If you want to copy files instead, you can replace the MoveHere function call with "CopyHere" instead. # But once again, the author can take no responsibility for the use, or misuse, of this script.</em> # param([string]$phoneName,[string]$sourceFolder,[string]$targetFolder,[string]$filter='(.jpg)|(.mp4)$') function Get-ShellProxy { if( -not $global:ShellProxy) { $global:ShellProxy = new-object -com Shell.Application } $global:ShellProxy } function Get-Phone { param($phoneName) $shell = Get-ShellProxy # 17 (0x11) = ssfDRIVES from the ShellSpecialFolderConstants (https://msdn.microsoft.com/en-us/library/windows/desktop/bb774096(v=vs.85).aspx) # => "My Computer" — the virtual folder that contains everything on the local computer: storage devices, printers, and Control Panel. # This folder can also contain mapped network drives. $shellItem = $shell.NameSpace(17).self $phone = $shellItem.GetFolder.items() | where { $_.name -eq $phoneName } return $phone } function Get-SubFolder { param($parent,[string]$path) $pathParts = @( $path.Split([system.io.path]::DirectorySeparatorChar) ) $current = $parent foreach ($pathPart in $pathParts) { if ($pathPart) { $current = $current.GetFolder.items() | where { $_.Name -eq $pathPart } } } return $current } $phoneFolderPath = $sourceFolder $destinationFolderPath = $targetFolder # Optionally add additional sub-folders to the destination path, such as one based on date $phone = Get-Phone -phoneName $phoneName $folder = Get-SubFolder -parent $phone -path $phoneFolderPath $items = @( $folder.GetFolder.items() | where { $_.Name -match $filter } ) if ($items) { $totalItems = $items.count if ($totalItems -gt 0) { # If destination path doesn't exist, create it only if we have some items to move if (-not (test-path $destinationFolderPath) ) { $created = new-item -itemtype directory -path $destinationFolderPath } Write-Verbose "Processing Path : $phoneName\$phoneFolderPath" Write-Verbose "Moving to : $destinationFolderPath" $shell = Get-ShellProxy $destinationFolder = $shell.Namespace($destinationFolderPath).self $count = 0; foreach ($item in $items) { $fileName = $item.Name ++$count $percent = [int](($count * 100) / $totalItems) Write-Progress -Activity "Processing Files in $phoneName\$phoneFolderPath" ` -status "Processing File ${count} / ${totalItems} (${percent}%)" ` -CurrentOperation $fileName ` -PercentComplete $percent # Check the target file doesn't exist: $targetFilePath = join-path -path $destinationFolderPath -childPath $fileName if (test-path -path $targetFilePath) { write-error "Destination file exists - file not moved:`n`t$targetFilePath" } else { $destinationFolder.GetFolder.MoveHere($item) if (test-path -path $targetFilePath) { # Optionally do something with the file, such as modify the name (e.g. removed phone-added prefix, etc.) } else { write-error "Failed to move file to destination:`n`t$targetFilePath" } } } } }
To call the script you need to supply:
- the name of the phone (or MTP device). This is as it appears in Windows Explorer, and is usually the name you have given to the device in its settings
- the path to the folder in the device. Usually starts with something like “Phone” or “Internal shared storage”, etc.
- the fully-qualified path to the folder on the computer to where you want to move the files.
- a regular expression for all the files you want to move. For example, for images and videos you might want ‘(.jpg)|(.mp4)$’
You can put the commands into a batch (command) script to move the files from several locations. Here is an example:
@echo off REM Example use of MoveFromPhone.ps1 to move pictures from a phone onto computer REM REM This Windows Command Line script is provided 'as-is', without any express or implied warranty. REM In no event will the author be held liable for any damages arising from the use of this script. REM REM Again, please note that when used with the 'MoveFromPhone.ps1' as originally written, REM files will be MOVED from you phone: they will be DELETED from the sourceFolder (the phone) REM and MOVED to the targetFolder (on the computer). REM powershell Set-ExecutionPolicy RemoteSigned -scope currentuser REM Camera files powershell.exe "& '%~dp0MoveFromPhone.ps1' -phoneName 'MyPhone' -sourceFolder 'Internal shared storage\DCIM\Camera' -targetFolder 'C:\Users\Public\Pictures\Camera' -filter '(.jpg)|(.mp4)$'" REM Facebook powershell.exe "& '%~dp0MoveFromPhone.ps1' -phoneName 'MyPhone' -sourceFolder 'Internal shared storage\DCIM\Facebook' -targetFolder 'C:\Users\Public\Pictures\Facebook' -filter '(.jpg)|(.mp4)$'" REM Screenshots powershell.exe "& '%~dp0MoveFromPhone.ps1' -phoneName 'MyPhone' -sourceFolder 'Internal shared storage\DCIM\Screenshots' -targetFolder 'C:\Users\Public\Pictures\Screenshots' -filter '(.png)$'" pause
Please feel free to comment if you spot any mistakes or have any ideas or suggestions for improvements.
I was asking how to open the MTP folder with a Powershell script and bat file but the question never showed up. I have since got the answer, here:
———————————————————————————-
Powershell script “Open_MTP.ps1”
———————————————————————————-
Param([string]$deviceName,
[string]$deviceFolderPath)
$shell = New-Object -com shell.application
$DeviceFolder = ($shell.NameSpace(“shell:MyComputerFolder”).Items() | where Name -eq $deviceName).GetFolder
$SourceFolderAsFolderItem = $DeviceFolderPath.Split(‘\’) |
ForEach-Object -Begin {
$comFolder = $DeviceFolder
} -Process {
Try
{
$comFolder = ($comFolder.Items() | where {$_.IsFolder} | where Name -eq $_).GetFolder
}
Catch
{
Write-Error ‘Failed to parse $DeviceFolderPath’
}
} -End {
$comFolder.Self
}
If ( $SourceFolderAsFolderItem )
{
$SourceFolderAsFolderItem.InvokeVerb()
}
———————————————————————————-
Batch file:
———————————————————————————-
:: Variables…
set DEVICE_NAME=”Some Phone”
set DEVICE_FOLDER_PATH=”Card\DCIM\Camera”
:: Open MTP folder…
Powershell -NoProfile -ExecutionPolicy Bypass -Command “& ‘%~dp0Open_MTP.ps1’ -deviceName ‘%DEVICE_NAME%’ -deviceFolder ‘%DEVICE_FOLDER_PATH%'”
exit
———————————————————————————-
This works well, but does anyone know what PS1 script and batch file commands work to simply open the MTP folder, without moving or copying files?
I must thank you for coming up with this solution!
I updated this script quite a bit to copy instead of move and deal with existing data on the destination. Because of MTP limitations and bugs in .CopyHere it is a little messy but works.
# Windows Powershell Script to copy a set of files (based on a filter) from a folder
# on a MTP device (e.g. Android phone) to a folder on a computer, using the Windows Shell.
# By Daiyan Yingyu, 19 March 2018, based on the (non-working) script found here:
# Updated by Daryl Greenwood December 6 2022 to copy and merge with exiting data that works around a bug in .CopyHere prompting
# https://www.pstips.net/access-file-system-against-mtp-connection.html
# as referenced here:
# https://powershell.org/forums/topic/powershell-mtp-connections/
#
# This Powershell script is provided ‘as-is’, without any express or implied warranty.
# In no event will the author be held liable for any damages arising from the use of this script.
#
# Again, please note that used ‘as-is’ this script will MOVE files from you phone:
# the files will be DELETED from the source (the phone) and MOVED to the computer.
#
# If you want to copy files instead, you can replace the MoveHere function call with “CopyHere” instead.
# But once again, the author can take no responsibility for the use, or misuse, of this script.
#
param([string]$phoneName,[string]$sourceFolder,[string]$targetFolder)
# This creates another Powershell script that will monitor for merge and copy prompts.
“param (`$Process)” | Out-file -Encoding ascii “$($env:temp)\pstemp.ps1”
“If(!(`$Process)){“”Nothing to monitor `$Process””;Start-Sleep -s 5;exit}” | Out-file -Encoding ascii -append “$($env:temp)\pstemp.ps1”
“`$wshell = new-object -com wscript.shell” | Out-file -Encoding ascii -append “$($env:temp)\pstemp.ps1”
“Do” | Out-file -Encoding ascii -append “$($env:temp)\pstemp.ps1”
“{” | Out-file -Encoding ascii -append “$($env:temp)\pstemp.ps1″
” If(`$wshell.appactivate(“”Confirm Folder Replace””)){`$wshell.SendKeys(‘y’)}” | Out-file -Encoding ascii -append “$($env:temp)\pstemp.ps1″
” If(`$wshell.appactivate(“”Copy File””)){`$wshell.SendKeys(“”{TAB}””)}” | Out-file -Encoding ascii -append “$($env:temp)\pstemp.ps1″
” If(`$wshell.appactivate(“”Copy File””)){`$wshell.SendKeys(“”{TAB}””)}” | Out-file -Encoding ascii -append “$($env:temp)\pstemp.ps1″
” If(`$wshell.appactivate(“”Copy File””)){`$wshell.SendKeys(“”{ENTER}””)}” | Out-file -Encoding ascii -append “$($env:temp)\pstemp.ps1″
” If(`$wshell.appactivate(“”Error Copying File or Folder””)){`$wshell.SendKeys(“”{ENTER}””)}” | Out-file -Encoding ascii -append “$($env:temp)\pstemp.ps1″
” start-sleep -Milliseconds 500″ | Out-file -Encoding ascii -append “$($env:temp)\pstemp.ps1”
“}” | Out-file -Encoding ascii -append “$($env:temp)\pstemp.ps1”
“While(Get-process | ? {`$_.id -match `$Process})” | Out-file -Encoding ascii -append “$($env:temp)\pstemp.ps1”
# When rerunning the script in psISE it will kill the existing process (if any) before launching another one.
If($P){Stop-process -Id $P.Id -Force -Confirm:$false -ErrorAction SilentlyContinue}
function Get-ShellProxy
{
if( -not $global:ShellProxy)
{
$global:ShellProxy = new-object -com Shell.Application
}
$global:ShellProxy
}
function Get-Phone
{
param($phoneName)
$shell = Get-ShellProxy
# 17 (0x11) = ssfDRIVES from the ShellSpecialFolderConstants (https://msdn.microsoft.com/en-us/library/windows/desktop/bb774096(v=vs.85).aspx)
# => “My Computer” — the virtual folder that contains everything on the local computer: storage devices, printers, and Control Panel.
# This folder can also contain mapped network drives.
$shellItem = $shell.NameSpace(17).self
$phone = $shellItem.GetFolder.items() | where { $_.name -eq $phoneName }
If(!($Phone)){$phone = $shellItem.GetFolder.items() | where { $_.type -eq “Mobile Phone”} | Select -First 1}
return $phone
}
function Get-SubFolder
{
param($parent,[string]$path)
$pathParts = @( $path.Split([system.io.path]::DirectorySeparatorChar) )
$current = $parent
foreach ($pathPart in $pathParts)
{
if ($pathPart)
{
Try{$current = $current.GetFolder.items() | where { $_.Name -eq $pathPart }}Catch{“Phone or source folder Not Found.”;exit}
}
}
return $current
}
# If not defined as a paramater, look for a device with a ‘type’ called “Mobile Phone” and return the first “Mobile Phone” found.
$phone = Get-Phone -phoneName $phoneName
# If not defined as a paramater, Look for the root drive of the phone, usually called “Internal shared storage”
If(!($sourceFolder)){$sourceFolder = $(($Folder = Get-SubFolder -parent $phone).GetFolder.Items()).name}
# If not defined as a paramater, create a folder on the desktop with the same name as the $sourceFolder
If(!($targetFolder)){$targetFolder = “$([Environment]::GetFolderPath(“Desktop”))\$($sourceFolder)”}
If(!(Test-Path $targetFolder)){New-Item -ItemType Directory -Path “$([Environment]::GetFolderPath(“Desktop”))\$($sourceFolder)”}
$phoneFolderPath = $sourceFolder
$destinationFolderPath = $targetFolder
$folder = Get-SubFolder -parent $phone -path $phoneFolderPath
# Get folder items excluding specific system folders
$items = @( $folder.GetFolder.items() | where {$_.name -notmatch “Android|.FileManagerRecycler”} ) | Sort-Object Name
# Starts the second powershell script that is monitoring the process and answering prompts because .copyhere paramaters are broken.
$P = start-process powershell.exe -argumentlist @(“-file”,”$env:temp\pstemp.ps1″,$PID) -PassThru -WindowStyle Minimized
# Process everything in $sourceFolder
if ($items)
{
# Only looks at the count in $sourceFolder
$totalItems = $items.count
if ($totalItems -gt 0)
{
Write-Verbose “Processing Path : $phoneName\$phoneFolderPath”
Write-Verbose “Copying to : $destinationFolderPath”
$shell = Get-ShellProxy
$destinationFolder = $shell.Namespace($destinationFolderPath).self
$count = 0;
foreach ($item in $items)
{
$fileName = $item.Name
++$count
$percent = [int](($count * 100) / $totalItems)
Write-Progress -Activity “Processing Folders in $phoneName\$phoneFolderPath” `
-status “Processing Folder ${count} / ${totalItems} (${percent}%)” `
-CurrentOperation $fileName `
-PercentComplete $percent
$targetFilePath = join-path -path $destinationFolderPath -childPath $fileName
$destinationFolder.GetFolder.CopyHere($item)
if (test-path -path $targetFilePath)
{
# Optionally do something with the file, such as modify the name (e.g. removed phone-added prefix, etc.)
}
else
{
write-error “Failed to move file to destination:`n`t$targetFilePath”
}
}
}
}
Thanks a lot Daiyan for the code sample!
The only thing I have a doubt about now would be how to perform the opposite action, move a file from the computer to the mobile device.
Also I would like to know if the action of deleting a file from the mobile device is possible.
Hello,
Thanks a lot for sharing this. I was able to retrieve my 6k+ pictures bypassing “Photos” app erros and explorer.
Your method of getting the phone folder didn’t work for me or I didn’t get it, the following lines modified around line 60 did the trick.
Select the DCIM folder in the iPhone when the file selector window appears.
———————————————————————————————-
#$phone = Get-Phone -phoneName $phoneName
#$folder = Get-SubFolder -parent $phone -path $phoneFolderPath
$ff = $app.BrowseForFolder(0,”Select Folder — Cancel to select ALL”,0,”Ce PC\Apple iPhone\Internal Storage\DCIM”)
foreach ($folder in $ff.Items()) {
$folder = $folder.GetFolder()
$items = @( $folder.Items() | where { $_.Name -match $filter } )
if ($items)
{
Glad you were able to modify it to work with iPhone.
I did mention in the comments that I’ve only used this with Android. (I didn’t even know it was possible with iPhone.)
I would suggest that you modify the methods “Get-Phone” and “Get-SubFolder” to make them work as expected, rather than by-passing them.
What is the “$app” variable?
“BrowseForFolder” appears to be a UI component – a dialogue to allow the user to search for a folder. One of the points of this script is to automate the process, rather than needing a user’s intervention.
Cheers.
Thank you very much for sharing 🙂 I use it to sync my GoPro
Would you be happy to share the working code? Trying to do the same and getting errors with my Hero10
Hi Daiyan,
Get-SubFolder function is not working as expected & is giving a Null Exception error. I have checked the logic one by one, but still the same. All variables are empty.
Is there anything you can do to help with, that would be very great?
Many Thanks,
Sajid
function Get-SubFolder
{
param($parent,[string]$path)
$pathParts = @( $path.Split([system.io.path]::DirectorySeparatorChar) )
$current = $parent
foreach ($pathPart in $pathParts)
{
if ($pathPart)
{
$current = $current.GetFolder.items() | where { $_.Name -eq $pathPart }
}
}
return $current
}
Hi Sajid,
Thanks for your feedback. It seems I didn’t put my updated script here.
Simply replace the line
if ($pathPart)
with
if ($current -and $pathPart)
and see if that solves your problem.
Sorry about that. When I have some time I will do a comparison of my example script with my working script to make sure it is up to date.
Cheers.
Howdy! I just want to offer you a huge thumbs up
for your excellent info you’ve got right here on this post.
I’ll be coming back to your site for more soon.
Thanks for a marvelous posting! I actually enjoyed reading it,
you are a great author. I will be sure to bookmark your blog and may come back at some point.
I want to encourage yourself to continue your great
job, have a nice evening!
Hi! Quick question that’s completely off topic.
Do you know how to make your site mobile friendly? My web site looks weird when browsing from
my iphone 4. I’m trying to find a theme or plugin that
might be able to resolve this problem. If you have any recommendations, please share.
With thanks!
Its like you read my mind! You seem to know a lot
about this, like you wrote the book in it or something.
I think that you could do with a few pics to drive the message home a little bit, but other than that, this is magnificent
blog. A fantastic read. I’ll certainly be back.
Nice response in return of this issue with firm arguments and telling all about that.
Aрpreciation to my father who informed me on the tօpіc of this weblog,
thіs blog is genuinely remarkaЬle.
Hello! Do you know if they make any plugins to assist with Search Engine Optimization? I’m trying
to get my blog to rank for some targeted keywords but I’m not seeing very good
success. If you know of any please share. Appreciate it!
Ԍreat blog! Do you have any hints for ɑspiring ԝriters?
I’m planning to start my own weЬsitе ѕoon but I’m a little lost on eveгything.
Would you suggest starting with a free platform like WordPress or go fօr a paid oρtion? There are so many options out there that I’m totɑlly cοnfused ..
Any ideas? Thanks a lot!
Great work! This is the kind of information that are supposed to be shared across the web.
Disgrace on Google for no longer positioning this post higher!
Come on over and discuss with my web site . Thank you
=)
I really like it when people come together and share opinions.
Great site, keep it up!
Howdy! This post could not be written any better!
Reading through this post reminds me of my old room mate!
He always kept chatting about this. I will forward this page to him.
Fairly certain he will have a good read. Thank you for sharing!
Hello, this weekend is nice in support of me, because this time i am reading this wonderful educational article
here at my house.
Howdy, i read your blog from time to time and i own a similar one and i was
just curious if you get a lot of spam comments? If so how do you reduce it, any plugin or anything you can suggest?
I get so much lately it’s driving me crazy so any assistance is very
much appreciated.
Yeah, I do get spam, but not too much so far. My sites are not very visible. I’m not yet sure how I would tackle it if I get much more. Maybe you could try something like Askimet Spam Protection?
Very nice post. I absolutely love this site. Continue the good work!
Hey, I think your blog might be having browser compatibility issues.
When I look at your website in Ie, it looks fine but when opening in Internet Explorer, it has some overlapping.
I just wanted to give you a quick heads up! Other then that, fantastic blog!
Thanks for the heads up, but I don’t know what browser you are referring to: “IE” is Internet Explorer. I just checked it using IE on Windows 8.1 and it looks fine, but IE really is a “dead” browser now anyway; it’s no longer being developed. As a standard up-to-date WP website, I hope the site works okay on all modern browsers. Cheers.
I have been exploring for a little for any high quality articles
or weblog posts on this sort of space . Exploring in Yahoo I at last stumbled upon this web
site. Reading this information So i’m glad to express
that I’ve a very good uncanny feeling I came upon exactly what I needed.
After looking over a few of the articles on your web site, I honestly like your
technique of blogging. I book marked it to my bookmark site list and will be checking
back soon. Please check out my website as well and let me know your opinion.
This design is steller! You obviously know how to keep a reader amused.
Between your wit and your videos, I was almost moved to start my own blog (well,
almost…HaHa!) Great job. I really enjoyed what you had to say,
and more than that, how you presented it. Too cool!
Howdy! I could have sworn I’ve been to your blog before but after going through many of the articles I realized it’s new to me. Regardless, I’m definitely happy I discovered it and I’ll be bookmarking it and checking back frequently!
Like!! Great article post.Really thank you! Really Cool.
I’m amazed, I must say. Seldom do I come across a blog that’s equally educative and engaging, and let me tell you, you have hit the nail on the head. The problem is something not enough folks are speaking intelligently about. Now i’m very happy I stumbled across this during my hunt for something concerning this.
You ought to be a part of a contest for one of the highest quality blogs on the internet. I’m going to highly recommend this site!
Wonderful blog! Do you have any recommendations for aspiring writers?
I’m hoping to start my own site soon but I’m a little lost on everything.
Would you suggest starting with a free platform like WordPress or go for a
paid option? There are so many choices out there that I’m
completely overwhelmed .. Any ideas? Appreciate it!
Hi Carol,
Thank you for your kind words. I looked at your page; it’s all in Chinese, but says you are from Sweden. When and why did you start learning Chinese?
As to your question, I don’t know which is best. I pay for this domain and web-space, using WordPress but mainly because I wanted a number of sub-domains, several of which host blogs with a lot of images and videos, but I am sure if you just want a single site I guess you can use wordpress.com directly, which I think is free, or if you just want a blog use something like blogspot.com if it still exists. Having your own domain gives you much more control though, and also means you have e-mail accounts and so on.
I am regular visitor, how are you everybody?
This article posted at this website is really good.
Thank you for some other excellent article. Where else could anybody get that type of info
in such an ideal manner of writing? I have a presentation subsequent week, and I’m at the look for such information.
In line 59 of your script:
Write-Verbose “Copying to : $destinationFolderPath”
You explicitly send to powershell the word “Copying”. These files are not being copied, they are being moved. Do you think this can cause a problem for anyone using your script? Personally, this has done irreparable damage. Fix your UX.
Thanks for the heads up. I have corrected it in the text and script file.
I am not sure why that got left in. I know in my early days of experimenting with this I was copying files instead of moving them (for obvious reasons), and one script I still use gives the option, with a function “CopyOrMoveFiles” (how that begins is shown at the end of this comment). The script in this post was one I edited from my original scripts to share with others to show how to do this, because my scripts do a lot more than this. I guess the Copy got left in from somewhere by mistake.
I can only apologise. I hope you are able to put the files back. I hope you don’t hold me responsible for any loss. I would point out that, aside from that text (which is only displayed when verbose output is on) and a comment, I believe it is pretty clear that the script is written to move the files:
1) it says so in my post – in fact “Move” appeared 14 times in the post, while “copy” appeared only four times; the paragraph before the script clearly says “The next problem was how to move the files. The original script uses the “MoveHere” shell method“. Furthermore I mentioned in the first paragraph that my purpose was for “cleaning pictures and other files off of my phone“.
2) it says so in the comment at the top of the script: “Windows Powershell Script to move a set of files“.
3) the function on the shell folder that does the job is called “MoveFile”: “GetFolder.MoveHere” is fairly prominent, as it appears in black amongst brown text.
4) BOTH example script files are called “MoveFromPhone” (MoveFromPhone.ps1 and MoveFromPhone.cmd), the command script calls the Powershell script and it has a comment at the top that says “Example use of MoveFromPhone.ps1 to move pictures from a phone“.
So, in short, I cannot believe anyone would not notice any of these references to “moving files” before running the script, which is when one was most likely to first notice the reference to “Copying”. But again apologise if this was you.
I think now I will add a disclaimer, and also make it more prominent that it is moving the files.
As mentioned above, this is how my “CopyOrMoveFiles” function starts:
function CopyOrMoveFiles
{
param($folder,[string]$destinationFolderPath,[switch]$moveFiles=$false,[string]$filter=$null,[int]$progressParentId=-1)
$copyText = ‘copy’
$copyingText = ‘Copying’
$copiedText = ‘copied’
if ($moveFiles)
{
$copyText = ‘move’
$copyingText = ‘Moving’
$copiedText = ‘moved’
}
# …
I will right away grasp your rss as I can not to find your email subscription link or e-newsletter service. Do you’ve any? Please allow me realize in order that I may subscribe. Thanks.|
Thank you for your kind words. I don’t have any kind of subscription. I didn’t know I have an RSS feed even! 😀 I’m sorry I haven’t written much on this blog yet. I am considering recreating some past posts at first, but I need to consider the purpose(s) of this blog to take it forward. In the meantime I have been working on other projects, and just hope to be able to get around to doing something with this blog in the not too distant future.
Another issue I have is that it seems apps on the phone sometimes keep files “locked” with one of two results:
1) the file is seen by the computer, but cannot be copied/moved; in which case the script throws up an error dialogue which you have to clear before it continues. I haven’t tried to fix this, because it’s kinda useful to know there’s been a problem. I can kill the script and run it again after sorting out the issue.
2) the file is not seen by the computer at all (even though it can be seen in a file browser on the phone)
The only way to solve either of these issues is make sure all apps are shut down on the phone (as far as possible) and then restart the phone. Sometimes even this hasn’t solved the “invisible file” problem, and I have to manually move the files on the phone to another folder or to the computer directly.
thanks for the code, i am now using it for backingup files from my iphone, real easy to use, i used to use file explorer to drag files from iphone folder and now can have it automated
one point need your advice, if u encountered before, i found iphone will become disconnected when copying big files like mov, it also happen before when i am using file explorer, so it is not your script issue, maybe some general iphone connectivitiy issue, btw, it happens at random, some mov file can be copied but some cannot…
i now use your script and filtering out those mov files, all other jpg/mp4 can be copied.
pls comment, thanks again
Thanks for the compliment, Michael.
I have never used an iPhone, so I didn’t even know this would work with one!
I think the only time I’ve had a similar problem is if the phone disconnects from the computer. The connection on my phone and/or computer is not tight, or the cable might be slightly “iffy”. Basically, to avoid this problem, I simply make sure the connection is in a stable state – connected, phone switched to Transfer Files mode, and computer has detected it – before running the script. And then, make sure not to move the phone (or computer), or touch the cable, etc, until the task has completed.
I appreciate, cause I found just what I was having a look for.
You’ve ended my four day long hunt! God Bless you man.
Have a nice day. Bye
This is very fascinating, You are an excessively skilled blogger. I’ve joined your feed and look ahead to looking for extra of your excellent post. Also, I have shared your website in my social networks|
I’m gone to inform my little brother, that he should also go to see this weblog on regular basis to get updated from latest information.|
I couldn’t resist commenting. Exceptionally well written!|
Thank you!
After examine just a few of the blog posts on your website now, and I really like your means of blogging. I bookmarked it to my bookmark website list and will be checking back soon. Pls check out my web page as nicely and let me know what you think.
You’re very kind. I had hoped to be more active than I have been, but I’ve been working on other projects.
Good blog you have got here.. It’s hard to find excellent writing like yours nowadays. I really appreciate individuals like you! Take care!!|
Is there any possibility to use the “-Recurse”?
Similar to there:
“Get-ChildItem $sourceFolder -Recurse -Include *.jpg, *.raw, *.jpeg”
I starded in this way
It seemed very simple and it worked until I tested with my phone.
I also used the folder tree based on the Year and Month.
Unfortunately, using Windows to access files through MTP doesn’t have that feature. This is the whole purpose of this script. If you know of another way via the USB connection, feel free to share it.
One other possible solution is to use FTP . If your phone is connected via wi-fi on a shared network with the computer to which you want to move the files, some phone File Manager apps can configure a FTP point. I guess it could be possible to write a script to automate getting files in that way. However, even whether that has “Get-ChildItem” or “-recurse” I don’t know. It might be faster than MTP.
Great script! Since my iPAD running iOS 15.x has a DCIM folder that only contains subfolders, so I created a ‘parent’ script to call your script once for *each* of them (so not truly recursive, it fits my need):
# Windows Powershell Script to call another script for each subfolder
# found in a specified MTP device’s folder.
#
# Essentially it’s just an abridged/truncated version of Daiyan’s full file move script here:
# https://blog.daiyanyingyu.uk/2018/03/20/powershell-mtp/
#
param([string]$phoneName,[string]$sourceFolder,[string]$targetFolder,[string]$filter='(.jpg)|(.mp4)$’)
function Get-ShellProxy
{
if( -not $global:ShellProxy)
{
$global:ShellProxy = new-object -com Shell.Application
}
$global:ShellProxy
}
function Get-Phone
{
param($phoneName)
$shell = Get-ShellProxy
$shellItem = $shell.NameSpace(17).self
$phone = $shellItem.GetFolder.items() | where { $_.name -eq $phoneName }
return $phone
}
function Get-SubFolder
{
param($parent,[string]$path)
$pathParts = @( $path.Split([system.io.path]::DirectorySeparatorChar) )
$current = $parent
foreach ($pathPart in $pathParts)
{
if ($current -and $pathPart)
{
$current = $current.GetFolder.items() | where { $_.Name -eq $pathPart }
}
}
return $current
}
$phoneFolderPath = $sourceFolder
$destinationFolderPath = $targetFolder
$phone = Get-Phone -phoneName $phoneName
$folder = Get-SubFolder -parent $phone -path $phoneFolderPath
$items = @( $folder.GetFolder.items() )
$totalItems = $items.count
if ($totalItems -gt 0) {
echo “Found $totalItems items.”
} else {
echo “Zero items found in $phoneFolderPath.”
exit
}
foreach ($item in $items) {
echo ” ”
$subfolder = $item.Name
$launchcmd = (“.\MoveFromPhone.ps1″)
$launchargs = (-join( `
” -phoneName ‘”,$phoneName,`
“‘ -sourceFolder ‘\”,$phoneFolderPath,”\”,$subfolder, `
“‘ -targetFolder ‘”, $destinationFolderPath,”\”,$subfolder, `
“‘ -filter ‘(.JPG)|(.MOV)|(.PNG)$'” `
))
powershell.exe “$launchcmd $launchargs”
}
Not sure my earlier comment went through, but I ended up putting a copy of this script + my minor changes on github, if it helps anyone –
https://github.com/gth/ipad-to-nas
My primitive tweak just does a single level of subfolders, but it wouldn’t be too hard to modify further to recurse all found folders.
Nice! But, having played with the shell object some, I can suggest a slight simplification in the Get-Phone function. The folder object returned the Namespace method is identical to $ShellItem.GetFolder. Try the following:
$Shell = new-object -comobject Shell.Application
$Shell.Namespace(17).Items | select name
$Shell.Namespace(17).self.GetFolder.Items() | select name
$shell.namespace(17) | gm
$Shell.Namespace(17).Self.GetFolder | gm
Peace!
I don’t quite understand what you are trying to achieve there.
The GetPhone method returns the folder object representing the supplied phone name. By doing “select name”, you’ll only return the name, which we already know. The code I supplied is making similar calls, but returning the phone object for iterating through the folders in the phone.
Could you explain more where you think it could be simplified?
Thank you. It is a very nice script
I have a question:
is it possible to retrieve modifieddate of the picture on the phone?
because I like to move/copy files after a certain datetime.
Hi Paul,
Thank you for your comment. I am sorry I didn’t spot it earlier. I haven’t been checking, because most comments are spam. Yours was the only one that even mentioned the content of the post.
Perhaps you have already got the answer. I did not post the full script that I use, because I wanted to focus on the actual method of copying or moving the files, but in fact my own script does indeed sort pictures by date/time.
I did not find a way to get the information from the file while it is on the phone, so it is copied or moved to a location on the computer, then the information obtained from the file there, a new name/location determined and the file moved (renamed) to the new location.
I first attempt to get the date taken property from within the picture itself. If that fails (i.e, no date-taken tag is available), get the modified time of the file (the original modified time should have been maintained by the copy or move, so this does seem to work for me).
So I have two functions, which take the path of the file on the computer. The first is called, and the second called if the first returns an empty string:
function GetPictureDateTakenString
{
param([string]$filePath)
$dateTakenString = ”
$OldErrorActionPref = $ErrorActionPreference
$ErrorActionPreference = “SilentlyContinue”
$pic = New-Object System.Drawing.Bitmap($filePath)
if ($pic)
{
$dateTakenBytes = $pic.GetPropertyItem(36867).Value
if ($dateTakenBytes)
{
$dateTakenString = [System.Text.Encoding]::ASCII.GetString($dateTakenBytes)
$dateTaken = [datetime]::ParseExact($dateTakenString,”yyyy:MM:dd HH:mm:ss`0″,$Null)
$dateTakenString = $dateTaken.tostring(“yyyyMMdd_HHmmss”)
}
$pic.Dispose()
$pic = $null
}
$ErrorActionPreference = $OldErrorActionPref
return $dateTakenString
}
function GetModifiedFileTimeString
{
param([string]$filePath)
$lastModifiedDate = (Get-Item $filePath).LastWriteTime
$dateTimeModifiedString = $lastModifiedDate.tostring(“yyyyMMdd_HHmmss”)
return $dateTimeModifiedString
}
I hope that’s helpful, even if it is rather late.