Solved

PowerShell - Move files - Slight issue

Posted on 2014-10-23
15
265 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Is Your AD Toolbox Looking More Like a Toybox?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

 
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 40

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 40

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 70

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 40

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 70

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 40

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

What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

Question has a verified solution.

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

Utilizing an array to gracefully append to a list of EmailAddresses
Recently we ran in to an issue while running some SQL jobs where we were trying to process the cubes.  We got an error saying failure stating 'NT SERVICE\SQLSERVERAGENT does not have access to Analysis Services. So this is a way to automate that wit…
In this Micro Tutorial viewers will learn how to use Boot Corrector from Paragon Rescue Kit Free to identify and fix the boot problems of Windows 7/8/2012R2 etc. As an example is used Windows 2012R2 which lost its active partition flag (often happen…
This tutorial will walk an individual through the process of installing of Data Protection Manager on a server running Windows Server 2012 R2, including the prerequisites. Microsoft .Net 3.5 is required. To install this feature, go to Server Manager…

737 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