question

AshleyLevendelis-9915 avatar image
0 Votes"
AshleyLevendelis-9915 asked RichMatheisen-8856 answered

How can I make this Powershell script better

Hi,

I'm new to Powershell scripting and I have made a simple script to move files from a downloads folder to other folders depending on file extension.
My script essentially does the same thing 4 times.

My question is, how can I write that script to be more effecient.

Thanks

Here it is:

Param (
[String]$Path
)

$ContainsTextFiles = $(Test-Path -Path $Path*.txt -PathType Leaf)
$ContainsMP3Files = $(Test-Path -Path $Path*mp3 -PathType Leaf )
$ContainsJPGFiles = $(Test-Path -Path $Path*.jpg -PathType Leaf)
$ContainsMP4Files = $(Test-Path -Path $Path*mp4 -PathType Leaf )


if ($ContainsTextFiles -eq $True) {
Move-Item -Path $Path*.txt -Destination C:\Users\Ashley\OneDrive\Documents\PowerShell\Project\Documents\
Write-Host "All .txt files have been succesfully moved to .\Documents"
}Else{
Write-Error "No .txt files exist"
}

if ($ContainsMP3Files -eq $True) {
Move-Item -Path $Path*.mp3 -Destination C:\Users\Ashley\OneDrive\Documents\PowerShell\Project\Music\
Write-Host "All .mp3 files have been succesfully moved to .\Music"
}Else{
Write-Error "No .mp3 files exist"
}

if ($ContainsJPGFiles -eq $True) {
Move-Item -Path $Path*.jpg -Destination C:\Users\Ashley\OneDrive\Documents\PowerShell\Project\Pictures\
Write-Host "All .jpg files have been succesfully moved to .\Pictures"
}Else{
Write-Error "No .jpg files exist"
}

if ($ContainsMP4Files -eq $True) {
Move-Item -Path $Path*.mp4 -Destination C:\Users\Ashley\OneDrive\Documents\PowerShell\Project\Videos\
Write-Host "All .mp4 files have been succesfully moved to .\Videos"
}Else{
Write-Error "No .mp4 files exist"
}

windows-server-powershell
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered

I guess that would depend on how you define efficiency! You script, as written, looks fairly efficient if a bit wordy.

I'd start by eliminating the four lines of tests that load the values like "$ContainsTextFiles" and just do the Test-Path in the "if" conditional statements.

To make it easier to add additional file types without adding a separate code block for each one, take the data values from, say a hash.

See if this works. I haven't run it, but I don't think it contains any errors that would prevent it from running:

 [CmdletBinding()]
 Param (
     [ValidateScript({$_ -match "\\$"})]     # must end with a trailing "\"
     [String]$Path
 )
    
 $Dest = "C:\Users\Ashley\OneDrive\Documents\PowerShell\Project\"
    
 $suffix = [ordered]@{
     '.txt' = 'Documents'
     '.mp3' = 'Music'
     '.jpg' = 'Pictures'
     '.mp4' = 'Videos'
 }
 $suffix.GetEnumerator()|
     ForEach-Object{
         $p = "{0}*{1}" -f $Path, $_.Key
         if ( (Test-Path -Path $p -PathType Leaf) ) {
             $d = "{0}{1}\" -f $Dest, $_.Value
             Move-Item -Path $p -Destination $d
             Write-Host "All $($_.Value) files have been succesfully moved to $Dest\$($_.Value)"
         }
         Else {
             Write-Error "No $($_.Key) files exist"
         }
     }

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered

If you'd rather create a reusable function that wouldn't require modifying the code that does the actual moving of the files every time you want to move a different set of file types (or move the same set to a different subdirectory), you could do it this way:

 # Define the function
 Function MoveThem{
     [CmdletBinding()]
     Param (
         [Parameter(Mandatory=$true)]
         [ValidateScript({$_ -match "\\$"})]     # must end with a trailing "\"
         [String]$Path,
    
         [Parameter(Mandatory=$true)]
         [ValidateScript({$_ -match "\\$"})]     # must end with a trailing "\"
         [String]$Dest,
    
         [Parameter(Mandatory=$true)]
         [System.Collections.Specialized.IOrderedDictionary]$types
     )
    
     $suffix.GetEnumerator()|
         ForEach-Object{
             $p = "{0}*{1}" -f $Path, $_.Key
             if ( (Test-Path -Path $p -PathType Leaf) ) {
                 $d = "{0}{1}\" -f $Dest, $_.Value
                 Move-Item -Path $p -Destination $d
                 Write-Host "All $($_.Value) files have been succesfully moved to $Dest\$($_.Value)"
             }
             Else {
                 Write-Error "No $($_.Key) files exist"
             }
         }
    
 # use the function with a complete set of parameters
 $suffix = [ordered]@{
     '.txt' = 'Documents'
     '.mp3' = 'Music'
     '.jpg' = 'Pictures'
     '.mp4' = 'Videos'
 }
 $Dest = "C:\Users\Ashley\OneDrive\Documents\PowerShell\Project\"
    
 MoveThem -Path .\ -Dest $Dest $suffix
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.