简体   繁体   中英

Powershell move all download to another folder function

I want to create a function to move file to a folder depending on the type of the file "C:\Users\dgoud\Desktop\TP4\Telechargement" to specific folder

I want to have the equivalent of this for PowerShell:

for root, dirs, files in os.walk("C:\Users\dgoud\Desktop\TP4\Telechargement"):

My PowerShell function:

 function DeplacerDansBonDossier {
            param (
                $extension
            )

        foreach ($file in $files) {
            $extn = [IO.Path]::GetExtension($line)
            if ($extn -eq ".txt" )
            {
                Move-Item -Path "C:\Users\dgoud\Desktop\TP4\Documents"
            }

            elseif ($extn -eq ".mp3" )
            {
                Move-Item -Path "C:\Users\dgoud\Desktop\TP4\Musique"
            }

            elseif ($extn -eq ".wav" )
            {
                Move-Item -Path "C:\Users\dgoud\Desktop\TP4\Musique"
            elseif ($extn -eq ".mp4" )
            {
                Move-Item -Path "C:\Users\dgoud\Desktop\TP4\VidBo"
            }

            elseif ($extn -eq ".mkv" )
            {
                Move-Item -Path "C:\Users\dgoud\Desktop\TP4\VidBo"
            }
        }
    }
}

I think this is what you are looking for. This function will only accept Files as input, note that I'm using Get-ChildItem -File below. Another point to consider is that, if there is a File with the same name on the Destination Folder Move-Item will throw with the following error:

Move-Item: Cannot create a file when that file already exists.

You can use -Force if you want to replace the existing files or add a new condition there if there is an existing file with the same name.

function DeplacerDansBonDossier {
[cmdletbinding()]
param(
    [parameter(mandatory,valuefrompipeline)]
    [System.IO.FileInfo]$File
)

    begin
    {
        $Paths = @{
            Documents = "C:\Users\dgoud\Desktop\TP4\Documents"
            Music = "C:\Users\dgoud\Desktop\TP4\Musique"
            Video = "C:\Users\dgoud\Desktop\TP4\VidBo"
        }
    }
    
    process
    {
        switch -Regex($File.Extension)
        {
            '^\.txt$'{
                $File | Move-Item -Destination $Paths['Documents']
                Write-Verbose ('Moved {0} to {1}' -f $file.Name,$Paths['Documents'])
                break
            }

            '^\.mp3$|^\.wav$'{
                $File | Move-Item -Destination $Paths['Music']
                Write-Verbose ('Moved {0} to {1}' -f $file.Name,$Paths['Music'])
                break
            }

            '^\.mp4$|^\.mkv$'{
                $File | Move-Item -Destination $Paths['Video']
                Write-Verbose ('Moved {0} to {1}' -f $file.Name,$Paths['Video'])
                break
            }
        }
    }
}

How to use the function:

Get-ChildItem 'C:\Users\dgoud\Desktop\TP4\Telechargement' -File | DeplacerDansBonDossier

# If you want to see which Files are being moved and their destination
# you can use -Verbose
Get-ChildItem 'C:\Users\dgoud\Desktop\TP4\Telechargement' -File | DeplacerDansBonDossier -Verbose 

It goes without saying that there are lots of ways to accomplish this. You may not need a function at all as these files could be piped directly to a ForEach-Object loop. At any rate, if we are using a function I would start by sending the collection of [FileInfo] objects generated by Get-ChildItem to the function. This is in place of the extension.

That might look something like this:

Function DeplacerDansBonDossier {
    param (
        $Files
    )

foreach ( $file in $files ) {
    $extn = $File.Extension
    
    if ($extn -eq ".txt" ) {
        Move-Item -Path $File -Destination "C:\Users\dgoud\Desktop\TP4\Documents" 
    }
    elseif ($extn -eq ".mp3" ) {
        Move-Item -Path $File -Destination "C:\Users\dgoud\Desktop\TP4\Musique"
    }
    elseif ($extn -eq ".wav" ) {
        Move-Item -Path $File -Destination "C:\Users\dgoud\Desktop\TP4\Musique"
    }
    elseif ($extn -eq ".mp4" ) {
        Move-Item -Path $File -Destination "C:\Users\dgoud\Desktop\TP4\VidBo"
    }
    elseif ($extn -eq ".mkv" ) {
        Move-Item -Path $File -Destination "C:\Users\dgoud\Desktop\TP4\VidBo"
    }
}

} # End Function DeplacerDansBonDossier

In your demo code you had the extension, but you didn't have the file object on hand so effectively there was nothing to move.

Another variation using the switch statement as @AbrahamZinala suggested:

Function DeplacerDansBonDossier {
    param (
        $Files
    )

foreach ($file in $files) {
    $extn = $File.Extension
    
    Switch ($extn)
    {
        '.txt' { Move-Item -Path $File -Destination "C:\Users\dgoud\Desktop\TP4\Documents"; Break }
        '.mp3' { Move-Item -Path $File -Destination "C:\Users\dgoud\Desktop\TP4\Musique";   Break }
        '.wav' { Move-Item -Path $File -Destination "C:\Users\dgoud\Desktop\TP4\Musique";   Break }
        '.mp4' { Move-Item -Path $File -Destination "C:\Users\dgoud\Desktop\TP4\VidBo";     Break }
        '.mkv' { Move-Item -Path $File -Destination "C:\Users\dgoud\Desktop\TP4\VidBo";     Break }
    }    
}

} # End Function DeplacerDansBonDossier

$Files = Get-ChildItem -Path C:\temp\SourceFolder

DeplacerDansBonDossier $Files

Obviously Switch makes things more concise, but not as descriptive. Also, note the break statements. Unlike If\ElseIf a Switch statement will evaluate more than 1 condition and script block. We stop that behavior with Break

Not to be redundant, but there's a lot more that could be done here. For example we could pipeline enable the function so it can be piped right after Get-ChildItem , but it may not be worth it considering aforementioned potential of ForEach-Object would operate much the same.

Example with ForEach-Object :

Get-ChildItem -Path C:\temp\SourceFolder |
ForEach-Object{
    foreach ( $file in $files ) {
        $extn = $File.Extension
        
        if ($extn -eq ".txt" ) {
            Move-Item -Path $_ -Destination "C:\Users\dgoud\Desktop\TP4\Documents" 
        }
        elseif ($extn -eq ".mp3" ) {
            Move-Item -Path $_ -Destination "C:\Users\dgoud\Desktop\TP4\Musique"
        }
        elseif ($extn -eq ".wav" ) {
            Move-Item -Path $_ -Destination "C:\Users\dgoud\Desktop\TP4\Musique"
        }
        elseif ($extn -eq ".mp4" ) {
            Move-Item -Path $_ -Destination "C:\Users\dgoud\Desktop\TP4\VidBo"
        }
        elseif ($extn -eq ".mkv" ) {
            Move-Item -Path $_ -Destination "C:\Users\dgoud\Desktop\TP4\VidBo"
        }
    }
}

Note: I wouldn't use Switch in the ForEach-Object script block. $_ operates differently in a Switch context.

Note: None of this is tested. You may need to use the .FullName property for the -Path argument, either $File.FullName or $_.FullName . the *-Item cmdlets can be fussy in that way.

Adding to the other great answers already, if the extensions always map to those paths, storing them in a hash table could be used here.

function DeplacerDansBonDossier {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory, ValueFromPipeline)]
        [System.IO.FileInfo]
        $File,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Username = $env:USERNAME
    )

    begin {
        $extensionDestinationMappings = @{
            ".txt" = "C:\Users\$Username\Desktop\TP4\Documents"
            ".mp3" = "C:\Users\$Username\Desktop\TP4\Musique"
            ".wav" = "C:\Users\$Username\Desktop\TP4\Musique"
            ".mp4" = "C:\Users\$Username\Desktop\TP4\VidBo"
            ".mkv" = "C:\Users\$Username\Desktop\TP4\VidBo"
        }
    }

    process {
        $extension = $File.Extension

        # Check extension exists in hashtable beforehand
        if ($extensionDestinationMappings.ContainsKey($extension)) {
            Move-Item -Path $File.FullName -Destination $extensionDestinationMappings[$extension] 
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM