I'm just beginning in Powershell - This will be my first full project, start to finish, and it's quite small. I have already had experience in C#, which helps in this .Net based language.
This program asks the user for the input folder (usually a media device), and colects the data (to sort). It also asks for the destination folder (usually named av
), and sorts the pictures into folders named like so:
L:\av\2015\03\Picture01.jpg
I've tested this with 200-300 photos, and it takes around a minute to complete. This seems like too much time to simply copy a few photos, although it is over the network (L
is a mapped drive). I tried comparing the same copy using my Powershell script and Windows Explorer, and as a matter of fact, they are almost the same. This leads me to believe that the speed can't really be improved (without changing computer equipment).
$pathToMedia = Read-Host 'Type the full path to your media device'
Write-Host("Great!")
$pathToDest = Read-Host 'Type in the path to the av (destination) folder (without trailing slash (\) )'
Write-Host("Awesome!")
Write-Host
$pictures = Get-ChildItem $pathToMedia | Where-Object {$_.Extension -eq ".jpg" -or $_.Extension -eq ".nef"} #get all the files with those extentions in this directory
$pictureCount = $pictures.Count
$array = new-object ‘object[,]’ $pictureCount,3 #use as follows: The first column will be an int; id. The sub-1 will be path, sub-2 will be date-year, and sub-3 will be date-month.
#e.g: 0,0 = /device/whatever/dc01.jpg
#0,1 = 2014
#0,2 = 09
#get
for($i=0; $i -lt $pictureCount; $i++) #note to self: $i++ increases the value after the loop runs
{
$picture = $pictures[$i]
$array[$i,0] = $picture.FullName #full file address - use for copying
$array[$i,1] = $picture.CreationTime.Year.ToString() #creation time of picture - use for sorting
if($picture.CreationTime.Month -lt 10)
{
$array[$i,2] = "0" + $picture.CreationTime.Month.ToString() #creation time of picture - use for sorting
}
else
{
$array[$i,2] = $picture.CreationTime.Month.ToString() #creation time of picture - use for sorting
}
}
#copy, sort
Write-Host "Copying files..."
for($i=0; $i -lt $pictureCount; $i++)
{
$dest = $pathToDest+"\"+$array[$i,1]+"\"+$array[$i,2]+"\"
if (!(Test-Path -path $dest))
{
New-Item $dest -Type Directory
Write-Host "Created directory."
Write-Host
}
Copy-Item $array[$i,0] $dest -ErrorAction Stop
}
Write-Host "Done!"
Write-Host
#delete source (option)
$deleteSource = Read-Host "Delete source files? (t/f)"
if ($deleteSource -eq "t")
{
Write-Host "Deleting source files."
Write-Host
}
elseif($deleteSource -eq "f")
{
Write-Host "Fine then. Not deleting source files."
Write-Host
}
else
{
Write-Host "Congrats! You found the magic chars that automatically delete the hard drive. System will automattically restart in 5 minutes."
Write-Host
}
Write-Host "Done!"
exit
Being new to Powershell, I wouldn't know if I'm missing out on something, or if my code does things wrong somehow. That is (now) one of my main objectives here. Thank you guys for helping!
EDIT
Here's my final code. I added many of the changes, and made parameters rather than the read-host
stuff.
[CmdletBinding()]
param(
[Parameter(
Mandatory=$true,
HelpMessage='Type the full path to your media device'
)]
[ValidateScript({Test-Path $_ -PathType 'Container'})]
[String]
$pathToMedia,
[Parameter(
Mandatory=$true,
HelpMessage='Type the full path to the destination for your photos'
)]
[ValidateScript({Test-Path $_ -PathType 'Container'})]
[String]
$pathToDest ,
[Parameter(
Mandatory=$false
)]
[switch]
$deleteSource = $false
)
Write-Host
# -or (throw "'pathToMedia' is not an absolute path, or the path does not exist.")
$exts = @('.jpg' , '.nef')
$pictures = Get-ChildItem $pathToMedia | Where-Object {$exts -icontains $_.Extension} #get all the files with those extentions in this directory
$pictureCount = $pictures.Count
$array = new-object ‘object[,]’ $pictureCount,3 #use as follows: The first column will be an int; id. The sub-1 will be path, sub-2 will be date-year, and sub-3 will be date-month.
#e.g: 0,0 = /device/whatever/dc01.jpg
#0,1 = 2014
#0,2 = 09
#get
for($i=0; $i -lt $pictureCount; $i++) #note to self: $i++ increases the value after the loop runs
{
$picture = $pictures[$i]
$array[$i,0] = $picture.FullName #full file address - use for copying
$array[$i,1] = $picture.CreationTime.Year.ToString() #creation time of picture - use for sorting
if($picture.CreationTime.Month -lt 10)
{
$array[$i,2] = "0" + $picture.CreationTime.Month.ToString() #creation time of picture - use for sorting
}
else
{
$array[$i,2] = $picture.CreationTime.Month.ToString() #creation time of picture - use for sorting
}
}
#copy, sort
if($deleteSource)
{
Write-Host "Moving files..."
for($i=0; $i -lt $pictureCount; $i++)
{
$dest = $pathToDest | Join-Path -ChildPath $array[$i,1] | Join-Path -ChildPath $array[$i,2]
if (!(Test-Path -path $dest))
{
New-Item $dest -Type Directory
Write-Host "Created directory."
Write-Host
}
Move-Item $array[$i,0] $dest -ErrorAction Stop
Write-Host -NoNewline "."
}
}
else
{
Write-Host "Copying files..."
for($i=0; $i -lt $pictureCount; $i++)
{
$dest = $pathToDest | Join-Path -ChildPath $array[$i,1] | Join-Path -ChildPath $array[$i,2]
if (!(Test-Path -path $dest))
{
New-Item $dest -Type Directory
Write-Host "Created directory."
Write-Host
}
Copy-Item $array[$i,0] $dest -ErrorAction Stop
}
}
Write-Host
Write-Host "Done!"
Write-Host
exit