PowerShell - Move files - Slight issue

I am in the process of building a simple script to move files, based off of extension and age, including sub folders.  I have two (very minor) issues I'd like to fix.

Here's the script

#-Move Files Older Than X days, of File Type Y, From Folder Z (And Sub Folders)-#
#
#~v.1.0~#
#~09/08/2014~#
#
#-Get Currnet Date-#
$Today = Get-Date
#
#-Set Retention Period, in days (X)-#
$Retention = "30"
#
#-Set the Target From Folder (Z)-#
$Path = "C:\Test"
#
#-Select File Type (Y)-#
$Extension = "*.wav"
#
#-Define LastWrite-#
$Lastwrite = $Today.AddDays(-$Retention)
#
#Set the Target To Folder
$Destination = "C:\backup\"
#
#-Create List of Files to Move-#
#-NOTE: "-Recurse" String will Move all items in child items/Sub Folders-#
$Files = Get-ChildItem $Path -Include $Extension -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}
#
#-Move Files, Echoing File Name-#
foreach ($File in $Files)
	{
	if ($File -ne $NULL)
		{
		write-host "Moving File $File" -ForegroundColor DarkRed
		Move-Item -Path $Path -Destination $Destination 
				{
					Join-Path $Destination $_.Parent.FullName.Substring($Path.length)
							}
				}
		else
			{
		Write-Host "Done"
			}
		}
#Physically Moves the folder.  Recreate base folder

Open in new window


The Issues:

1.  When I run the move, the base folder is removed (which makes sense - it's a move).  But I'd really like to just move everything inside the folder.  I did try to use "mkdir" to recreate the folder, but I get an error that the folder already exists.   Not too sure how to force the mkdir after the full move has completed.

2.  I'm echoing back each file, and for each I get the following error,  although the files move without issue.  I'd liek to know why and if it can be cleaned up:


Moving File C:\Test\ShoreTel Call Recorder\TempRecordings\000C0000-090A-5407-FC20-0010490B12E0_41ltd245.wav
Move-Item : Cannot find path 'C:\Test' because it does not exist.
At C:\PS Scripts\MoveFilesAfterXDaysWSubs.ps1:34 char:3
+         Move-Item -Path $Path -Destination $Destination
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Test:String) [Move-Item], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.MoveItemCommand


                    Join-Path $Destination $_.Parent.FullName.Substring($Path.length)

Open in new window

LVL 1
JamesonJendreasAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Joshua GrantomSenior Systems AdministratorCommented:
Hello, you were getting the error because you were actually moving the entire folder instead of just the files.

the Move-Item should have been -Path $file instead of $Path (this is the folder itself)
#-Move Files Older Than X days, of File Type Y, From Folder Z (And Sub Folders)-#
#
#~v.1.0~#
#~09/08/2014~#
#
#-Get Currnet Date-#
$Today = Get-Date
#
#-Set Retention Period, in days (X)-#
$Retention = "30"
#
#-Set the Target From Folder (Z)-#
$Path = "C:\Test"
#
#-Select File Type (Y)-#
$Extension = "*.wav"
#
#-Define LastWrite-#
$Lastwrite = $Today.AddDays(-$Retention)
#
#Set the Target To Folder
$Destination = "C:\backup\"
#
#-Create List of Files to Move-#
#-NOTE: "-Recurse" String will Move all items in child items/Sub Folders-#
$Files = Get-ChildItem $Path -Include $Extension -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}
#
#-Move Files, Echoing File Name-#
foreach ($File in $Files)
	{
	if ($File -ne $NULL)
		{
		write-host "Moving File $File" -ForegroundColor DarkRed
		Move-Item -Path $file -Destination $Destination
							}
		else
			{
			}
		}
Write-Host "Done moving files" -ForegroundColor Cyan
#Physically Moves the folder.  Recreate base folder

Open in new window

0
JamesonJendreasAuthor Commented:
Bah!!!  I should have realized that.  Thanks!
0
Joshua GrantomSenior Systems AdministratorCommented:
It happens lol, Glad to help.
0
Has Powershell sent you back into the Stone Age?

If managing Active Directory using Windows Powershell® is making you feel like you stepped back in time, you are not alone.  For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why.

JamesonJendreasAuthor Commented:
Shoot (and this makes sense) looks like my Join-path is not working properly, as I'm not getting my folder structure. Which makes sense why it was copying the folder structure when moving the entire folder.  

Now i gotta figure out why my join-path isn't working.  It's actually just printing the string out:

Moving File C:\Test\ShoreTel Call Recorder\Recordings\Support\User1\Caller1\13-12-474156807
503.wav

                    Join-Path $Destination $_.Parent.FullName.Substring($Path.length)

Open in new window

*** Edit: Personal info removed - Qlemo, Topic Advisor ***
0
Joshua GrantomSenior Systems AdministratorCommented:
You shouldn't need the join path at all. $file has the entire path. If you let me know what you are trying to do with it I could possibly help

I would also request attention on this so a moderator can remove your users information from your last post.
0
JamesonJendreasAuthor Commented:
Seems to not be copying the folder structure when I remove the Join-path

#-Move Files Older Than X days, of File Type Y, From Folder Z (And Sub Folders)-#
#
#~v.1.0~#
#~09/08/2014~#
#
#-Get Currnet Date-#
$Today = Get-Date
#
#-Set Retention Period, in days (X)-#
$Retention = "1"
#
#-Set the Target From Folder (Z)-#
$Path = "C:\Test\"
#
#-Select File Type (Y)-#
$Extension = "*.wav"
#
#-Define LastWrite-#
$Lastwrite = $Today.AddDays(-$Retention)
#
#Set the Target To Folder
$Destination = "C:\backup\"
#
#-Create List of Files to Move-#
#-NOTE: "-Recurse" String will Move all items in child items/Sub Folders-#
$Files = Get-ChildItem $Path -Include $Extension -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}
#
#-Move Files, Echoing File Name-#
foreach ($File in $Files)
	{
	if ($File -ne $NULL)
		{
		write-host "Moving File $File" -ForegroundColor DarkRed
		Move-Item -Path $files -Destination $Destination 
								}
		else
			{
		Write-Host "Done"
			}
		}

Open in new window

0
Joshua GrantomSenior Systems AdministratorCommented:
Just an FYI, your above script is still using the wrong variable for move-Item. It $file not files

Move-Item -Path $file -Destination $Destination

I know there is a way to maintain structure also, looking into that.
0
footechCommented:
This should work.  I also reworked the If condition check as this way makes more sense.
#-Move Files Older Than X days, of File Type Y, From Folder Z (And Sub Folders)-#
#
#~v.1.0~#
#~09/08/2014~#
#
#-Get Currnet Date-#
$Today = Get-Date
#
#-Set Retention Period, in days (X)-#
$Retention = "30"
#
#-Set the Target From Folder (Z)-#
$Path = "C:\Test"
#
#-Select File Type (Y)-#
$Extension = "*.wav"
#
#-Define LastWrite-#
$Lastwrite = $Today.AddDays(-$Retention)
#
#Set the Target To Folder
$Destination = "C:\backup"
#
#-Create List of Files to Move-#
#-NOTE: "-Recurse" String will Move all items in child items/Sub Folders-#
$Files = Get-ChildItem $Path -Include $Extension -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}
if ($Files)
{
    #
    #-Move Files, Echoing File Name-#
    foreach ($File in $Files)
    {
        Write-Host "Moving File $File" -ForegroundColor DarkRed
        $fileDest = $File.FullName -replace "$Path","$Destination"
        Move-Item -Path $File.FullName -Destination $fileDest
    }
}
else
{
	Write-Host "Done"
}

Open in new window

0
Joshua GrantomSenior Systems AdministratorCommented:
footech is a G,

I'm still working on my Powershell know-how
0
footechCommented:
I'm not even close. :)
I noticed a mistake in what I posted.  Here's a correction.  You'll need to make sure that $Destination doesn't end with a "\" if you change it.
    foreach ($File in $Files)
    {
        Write-Host "Moving File $File" -ForegroundColor DarkRed
        $pattern = [regex]::Escape($Path)
        $fileDest = $File.FullName -replace "$pattern","$Destination"
        Move-Item -Path $File.FullName -Destination $fileDest
    }

Open in new window


I've actually worked on a version of this that uses Split-Path and Join-Path, but it's a fair amount more complex.
0
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
Line 26 is bad use of date vars (converting to strings and back to datetime):
$Files = Get-ChildItem $Path -Include $Extension -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}

Open in new window

should be
$Files = Get-ChildItem $Path -Include $Extension -Recurse | Where {$_.LastWriteTime -le $LastWrite}

Open in new window

to keep dates as dates.

And, btw, using split-path and join-path is a PITA ;-)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
footechCommented:
@Qlemo - Good catch!  RE: split- and join-path, I think the toughest part is handling the subfolder depth (i.e. how many parent folders for the source file do you want to recreate at the destination?).  I was working on a function that would take both input piped from Get-ChildItem or from an explicitly defined source path.  At one point I thought I had finished it, but then came up with some scenarios which it didn't handle the way I wanted.  Sometimes that's the problem - deciding when what you have is good enough.  :)

Line 4 in the last code bit I posted should also be moved up to before the foreach loop - no need to keep redefining the same thing repeatedly.
0
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
It's a pitty you cannot just say "keep three levels" with split-path - would make things much easier.
0
footechCommented:
Agreed.
0
JamesonJendreasAuthor Commented:
Thanks Everyone!  I hope it's Ok I split points, all information provided was extremely useful, and getting me better with my PowerShell-foo (it's about time, but I love Powershell)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.