简体   繁体   English

Powershell 将所有下载移动到另一个文件夹 function

[英]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我想创建一个 function 将文件移动到一个文件夹,具体取决于文件“C:\Users\dgoud\Desktop\TP4\Telechargement”到特定文件夹的类型

I want to have the equivalent of this for PowerShell:我想为 PowerShell 提供等价物:

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

My PowerShell function:我的 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.这个 function 将只接受文件作为输入,请注意我在下面使用Get-ChildItem -File 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上有同名File ,则会抛出以下错误:

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.如果要替换现有文件,则可以使用-Force ,如果存在同名的现有文件,则可以在其中添加新条件。

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: 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.您可能根本不需要 function,因为这些文件可以直接通过管道传输到ForEach-Object循环。 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.无论如何,如果我们使用 function,我会首先将Get-ChildItem生成的[FileInfo]对象的集合发送到 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.在您的演示代码中,您有扩展名,但您手头没有 object 文件,因此实际上没有什么可移动的。

Another variation using the switch statement as @AbrahamZinala suggested: @AbrahamZinala 建议使用 switch 语句的另一个变体:

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.显然Switch使事情更简洁,但没有描述性。 Also, note the break statements.另外,请注意break语句。 Unlike If\ElseIf a Switch statement will evaluate more than 1 condition and script block.If\ElseIf不同, Switch语句将评估多个条件和脚本块。 We stop that behavior with Break我们用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.例如,我们可以通过管道启用 function 以便它可以在Get-ChildItem之后立即进行管道传输,但考虑到上述ForEach-Object的潜力将运行大致相同,这可能不值得。

Example with ForEach-Object : 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.注意:我不会在ForEach-Object脚本块中使用Switch $_ operates differently in a Switch context. $_Switch上下文中的操作方式不同。

Note: None of this is tested.注意:这些都没有经过测试。 You may need to use the .FullName property for the -Path argument, either $File.FullName or $_.FullName .您可能需要为-Path参数使用.FullName属性,即$File.FullName$_.FullName the *-Item cmdlets can be fussy in that way. *-Item cmdlet 在这种情况下可能会很麻烦。

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.已经添加到其他很好的答案,如果扩展总是 map 到这些路径,则可以在此处使用将它们存储在 hash 表中。

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] 
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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