Solved

PowerShell - Move files - Slight issue

Posted on 2014-10-23
15
255 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
Enterprise Mobility and BYOD For Dummies

Like “For Dummies” books, you can read this in whatever order you choose and learn about mobility and BYOD; and how to put a competitive mobile infrastructure in place. Developed for SMBs and large enterprises alike, you will find helpful use cases, planning, and implementation.

 
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
 
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 69

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 69

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

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

You might have come across a situation when you have Exchange 2013 server in two different sites (Production and DR). After adding the Database copy in ECP console it displays Database copy status unknown for the DR exchange server. Issue is strange…
The following article is intended as a guide to using PowerShell as a more versatile and reliable form of application detection in SCCM.
This tutorial will walk an individual through the steps necessary to join and promote the first Windows Server 2012 domain controller into an Active Directory environment running on Windows Server 2008. Determine the location of the FSMO roles by lo…
This tutorial will walk an individual through the process of configuring basic necessities in order to use the 2010 version of Data Protection Manager. These include storage, agents, and protection jobs. Launch Data Protection Manager from the deskt…

813 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

14 Experts available now in Live!

Get 1:1 Help Now