Solved

PowerShell - Move files - Slight issue

Posted on 2014-10-23
15
246 Views
Last Modified: 2014-10-29
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
Comment
Question by:JamesonJendreas
  • 5
  • 4
  • 4
  • +1
15 Comments
 
LVL 16

Assisted Solution

by:Joshua Grantom
Joshua Grantom earned 125 total points
ID: 40400328
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
 
LVL 1

Author Comment

by:JamesonJendreas
ID: 40400360
Bah!!!  I should have realized that.  Thanks!
0
 
LVL 16

Expert Comment

by:Joshua Grantom
ID: 40400370
It happens lol, Glad to help.
0
 
LVL 1

Author Comment

by:JamesonJendreas
ID: 40400371
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
 
LVL 16

Expert Comment

by:Joshua Grantom
ID: 40400384
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
 
LVL 1

Author Comment

by:JamesonJendreas
ID: 40400415
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
 
LVL 16

Expert Comment

by:Joshua Grantom
ID: 40400516
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
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 39

Assisted Solution

by:footech
footech earned 250 total points
ID: 40400589
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
 
LVL 16

Expert Comment

by:Joshua Grantom
ID: 40400603
footech is a G,

I'm still working on my Powershell know-how
0
 
LVL 39

Expert Comment

by:footech
ID: 40400763
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
 
LVL 68

Accepted Solution

by:
Qlemo earned 125 total points
ID: 40401972
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
 
LVL 39

Assisted Solution

by:footech
footech earned 250 total points
ID: 40402556
@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
 
LVL 68

Expert Comment

by:Qlemo
ID: 40402606
It's a pitty you cannot just say "keep three levels" with split-path - would make things much easier.
0
 
LVL 39

Expert Comment

by:footech
ID: 40402640
Agreed.
0
 
LVL 1

Author Closing Comment

by:JamesonJendreas
ID: 40411502
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

Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!

Join & Write a Comment

Active Directory replication delay is the cause to many problems.  Here is a super easy script to force Active Directory replication to all sites with by using an elevated PowerShell command prompt, and a tool to verify your changes.
The recent Microsoft changes on update philosophy for Windows pre-10 and their impact on existing WSUS implementations.
In this Micro Tutorial viewers will learn how they can get their files copied out from their unbootable system without need to use recovery services. As an example non-bootable Windows 2012R2 installation is used which has boot problems.
This tutorial will walk an individual through the process of configuring their Windows Server 2012 domain controller to synchronize its time with a trusted, external resource. Use Google, Bing, or other preferred search engine to locate trusted NTP …

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now