Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 310
  • Last Modified:

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

0
JamesonJendreas
Asked:
JamesonJendreas
  • 5
  • 4
  • 4
  • +1
4 Solutions
 
Joshua GrantomSenior EngineerCommented:
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 EngineerCommented:
It happens lol, Glad to help.
0
Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. 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 EngineerCommented:
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 EngineerCommented:
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 EngineerCommented:
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
 
QlemoC++ DeveloperCommented:
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
 
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
 
QlemoC++ DeveloperCommented:
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

Featured Post

Evaluating UTMs? Here's what you need to know!

Evaluating a UTM appliance and vendor can prove to be an overwhelming exercise.  How can you make sure that you're getting the security that your organization needs without breaking the bank? Check out our UTM Buyer's Guide for more information on what you should be looking for!

  • 5
  • 4
  • 4
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now