• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 574
  • Last Modified:

Powershell to move files based on split filenames

Good afternoon Experts!

I have been trying to figure out a way to automatically move files to specific directories based on the names or "$_.lastwritetime.month" value of the files but am completely stuck due to variables. I hope that one of you could guide me in the right direction.

Let me explain the scenario:
We have a software that records all the phonecalls at our office and dumps them as mp3-files in a root directory once they are disconnected. The files are automatically named using a standard looking like: YYYYMMDD. What I would like to do is script an automated way to move these files to subdirectories once per night after office hours. There is currently around 100 GB of files that date back to 2010.

Let me pose an actual example:
a.) Let's say that we have our root directory: "F:\Finished Recordings\".
b.) Let us say that we have a file from last year: 20110510...mp3.
c.) Let us say that we have another file, this one from today: 20120824...mp3.

Based on the above I want the script to move the first file (b.) to "F:\Finished Recordings\2011\May\" and the second file (c.) to "F:\Finished Recordings\2012\August\".
The destination directories are allready created, so all I want is to move the files based on their first 6 numbers. Is there a clever way to acomplish this? Thank you!
0
TrustJoLo
Asked:
TrustJoLo
  • 7
  • 6
1 Solution
 
dicconbCommented:
Hi TrustJoLo,

This script should do the trick:

Param (
	[Parameter(Mandatory=$true)]$rootfolder,
	$confirm=$true
)
[array]$unsorted_files = Get-ChildItem $rootfolder -Filter "*.mp3"
if ($unsorted_files.count -lt 1) {Return "No files to copy.  Exiting..."}
foreach ($file in $unsorted_files) {
	$yearnum = [string]::Join('',($file.name)[0..3])
	$monthnum = [string]::Join('',($file.name)[4..5])
	$monthname = (Get-Date -Month $monthnum -Format "MMMM")
	$newfolder = "$rootfolder\$yearnum\$monthname\"
	if (-not(Test-Path ($newfolder))) {mkdir ($newfolder) | Out-Null}
	Try {
		Move-Item -Path $file.Fullname -Destination $newfolder -confirm:$confirm | Out-Null
	} Catch {
		Throw ("Error moving file " + $file.FullName)
		$Error
	}
}

Open in new window

Save it as a file called something like FileOldRecordings.ps1

If you right-click it and click "Run with Powershell" it will prompt you for the root folder path and ask you for confirmation every time it moves a file.  Once you're happy that it's doing the job, you can run it with the following command-line:

C:\somefolder\FileOldRecordings.ps1 -rootfolder "F:\Finished Recordings\" -confirm:$false

Open in new window

Let me know if you have any problems, or questions about how the script works.

Cheers,

D
0
 
TrustJoLoAuthor Commented:
Hi Diccon!

I will try this out once I get back to work on monday.
Thank you for the quick response. :-)

Best regards,
A
0
 
dicconbCommented:
No probs. have a good weekend! D
0
What Security Threats Are We Predicting for 2018?

Cryptocurrency, IoT botnets, MFA, and more! Hackers are already planning their next big attacks for 2018. Learn what you might face, and how to defend against it with our 2018 security predictions.

 
dicconbCommented:
Hi TrustJoLo,

Did you get a chance to try out the script?

Cheers,

D
0
 
TrustJoLoAuthor Commented:
Hi D,

Unfortunately I have not been able to test it out, but since I understand you want the question marked as answered I will give you your well-earned points and hope for the best. :-)

Once again, thank you!

A
0
 
dicconbCommented:
Hi A,

Thanks for the points, although there really was no rush. Mainly I wanted to check that it worked as you expected! Let me know if you have any questions when you get round to testing it.

Cheers,

D
0
 
TrustJoLoAuthor Commented:
Hi D,

Just wanted to let you know that the script worked flawlessly after some minor alterations. It even uses swedish names for the months.

Thank you very much! :-)

// Alex
0
 
dicconbCommented:
Great news, thanks for letting me know!

Would you consider posting the new code in case someone else would benefit from your alterations?

Cheers,

D
0
 
TrustJoLoAuthor Commented:
The alterations were made to the server environment itself, namely allowing remotely signed scripts. The code did exactly what it was intended for.

Speaking of something different, as I have your attention anyway:
I have a scheduled task that executes a bat-file which initiates a robocopy from the non-domain computer where the files are originally created which works well.

Is there any way to incorporate a few lines to execute the PS-script after the robocopy process has finished? I am getting parser errors. The line I am trying to include in the bat-script at the very end is:

powershell.exe "& 'F:\Recorded Calls\MoveItems.ps1'" -rootfolder "F:\Recorded Calls\Compliance\" -confirm:$false >> F:\Logs\MoveItems.txt.
0
 
dicconbCommented:
Try this:

powershell.exe 'F:\Recorded Calls\MoveItems.ps1' -rootfolder 'F:\Recorded Calls\Compliance\' -confirm:$false >> F:\Logs\MoveItems.txt

Open in new window


Cheers,

D
0
 
TrustJoLoAuthor Commented:
Been trying all types of different variations, but still not getting it to work.
Different type of error now, though:
"You must provide a value expression on the right-hand side of the '-' operator.

Cheers,
Alex
0
 
dicconbCommented:
Curious! I wonder if the batch interpreter is doing something funny with "$false" that's stopping it being passed correctly.

Unfortunately I'm not by a computer at the moment so can't test anything, but I'm sure if you post the error you're getting as a separate question one of the other Powershell experts will be able to help. If not I'll take a look this evening.

Cheers,

D
0
 
TrustJoLoAuthor Commented:
I finally managed to sort this out. This is how I did (if anyone should come across this post in the future).

Firstly: In order to get rid of the problems of the batch interpreter not passing the powershell specific definitions, I got rid of the rootfolder variable of the original code as well as changing the confirmation requirement.

Like so: $confirm=$false
Replaced $rootfolder in both instances to the actual filepath. "F:\Copied Recordings\Compliance" in this case.

Secondly: I saved the .ps1-file in the same folder as the .bat.

Lastly: I amended the .bat-file making it look like below.

net use R: /delete
net use R: \\10.201.4.10\Move /user:computername\serviceaccount password
ROBOCOPY.exe \\10.201.4.10\Move "F:\Copied Recordings\Compliance" /MOV /XD *"Old files" /LOG:"F:\Copied Recordings\Logs\CopyRecordings.txt" /R:1 /W:1
powershell.exe .\MoveItems.ps1 > "F:\Copied Recordings\Logs\MoveItems.log"

Open in new window


I have succesfully ran this as a scheduled task, regardless of wether I am logged on or not. The "net use" is for establishing credentials as the source machine is not part of the same domain.

Thanks alot for your insight, Diccon!

Best regards,
Alex
0

Featured Post

Making Bulk Changes to Active Directory

Watch this video to see how easy it is to make mass changes to Active Directory from an external text file without using complicated scripts.

  • 7
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now