简体   繁体   中英

PowerShell Copy All Files in Folders and Sub=Folders Not older than 300 minutes

I am trying to copy all files in folders and sub-folders not older than 300 minutes, but the code I got working only copies the files in the main folder, it doesn't copy the files in subfolders. At the destination I don't want to maintain the folder structure of the original files, I just want to put all the origin files into a single specific destination folder. This is the code I have:

Powershell -NoL -NoP -C "&{$ts=New-TimeSpan -M 300;"^
 "Get-ChildItem "C:\Origin" -Filter '*.dat'|?{"^
 "$_.LastWriteTime -gt ((Get-Date)-$ts)}|"^
 %%{Copy-Item $_.FullName 'C:\Destination'}}"

Could someone help me out please? Thanks in advance.

Here's a modified script for you you can save as "Copy-Unique.ps1" you can run from a batch file.

function Copy-Unique {
    # Copies files to a destination. If a file with the same name already exists in the destination,
    # the function will create a unique filename by appending '(x)' after the name, but before the extension. 
    # The 'x' is a numeric sequence value.
    [CmdletBinding(SupportsShouldProcess)]  # add support for -WhatIf switch
    Param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
        [Alias("Path")]
        [ValidateScript({Test-Path -Path $_ -PathType Container})]
        [string]$SourceFolder,

        [Parameter(Mandatory = $true, Position = 1)]
        [string]$DestinationFolder,

        [Parameter(Mandatory = $false)]
        [int]$NewerThanMinutes = -1,

        [Parameter(Mandatory = $false)]
        [string]$Filter = '*',

        [switch]$Recurse
    )

    # create the destination path if it does not exist
    if (!(Test-Path -Path $DestinationFolder -PathType Container)) {
        Write-Verbose "Creating folder '$DestinationFolder'"
        $null = New-Item -Path $DestinationFolder -ItemType 'Directory' -Force
    }
    # get a list of file FullNames in this source folder
    $sourceFiles = @(Get-ChildItem -Path $SourceFolder -Filter $Filter -File -Recurse:$Recurse)
    # if you want only files not older than x minutes, apply an extra filter
    if ($NewerThanMinutes -gt 0) {
        $sourceFiles = @($sourceFiles | Where-Object { $_.LastWriteTime -gt (Get-Date).AddMinutes(-$NewerThanMinutes) })
    }
    foreach ($file in $sourceFiles) {
        # get an array of all filenames (names only) of the files with a similar name already present in the destination folder
        $destFiles = @((Get-ChildItem $DestinationFolder -File -Filter "$($file.BaseName)*$($file.Extension)").Name)
        # for PowerShell version < 3.0 use this
        # $destFiles = @(Get-ChildItem $DestinationFolder -Filter "$baseName*$extension" | Where-Object { !($_.PSIsContainer) } | Select-Object -ExpandProperty Name)

        # construct the new filename
        $newName = $file.Name
        $count = 1
        while ($destFiles -contains $newName) {
            $newName = "{0}({1}){2}" -f $file.BaseName, $count++, $file.Extension
        }
        # use Join-Path to create a FullName for the file
        $newFile = Join-Path -Path $DestinationFolder -ChildPath $newName
        Write-Verbose "Copying '$($file.FullName)' as '$newFile'"

        $file | Copy-Item -Destination $newFile -Force
    }
}

# you can change the folder paths, file pattern to filter etc. here
$destFolder = Join-Path -Path 'C:\Destination' -ChildPath ('{0:yyyy-MM-dd_HH-mm}' -f (Get-Date))
Copy-Unique -SourceFolder "C:\Origin" -DestinationFolder $destFolder -Filter '*.dat' -Recurse -NewerThanMinutes 300

Changed the code to now take a datetime object to compare against rather than an amount of minutes. This perhaps makes the code easier to understand, but certainly more flexible.

function Copy-Unique {
    # Copies files to a destination. If a file with the same name already exists in the destination,
    # the function will create a unique filename by appending '(x)' after the name, but before the extension. 
    # The 'x' is a numeric sequence value.
    [CmdletBinding(SupportsShouldProcess)]  # add support for -WhatIf switch
    Param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
        [Alias("Path")]
        [ValidateScript({Test-Path -Path $_ -PathType Container})]
        [string]$SourceFolder,

        [Parameter(Mandatory = $true, Position = 1)]
        [string]$DestinationFolder,

        [string]$Filter = '*',

        [datetime]$NewerThan = [datetime]::MinValue,

        [switch]$Recurse
    )

    # create the destination path if it does not exist
    if (!(Test-Path -Path $DestinationFolder -PathType Container)) {
        Write-Verbose "Creating folder '$DestinationFolder'"
        $null = New-Item -Path $DestinationFolder -ItemType 'Directory' -Force
    }
    # get a list of file FullNames in this source folder
    $sourceFiles = @(Get-ChildItem -Path $SourceFolder -Filter $Filter -File -Recurse:$Recurse)
    # if you want only files newer than a certain date, apply an extra filter
    if ($NewerThan -gt [datetime]::MinValue) {
        $sourceFiles = @($sourceFiles | Where-Object { $_.LastWriteTime -gt $NewerThan })
    }
    foreach ($file in $sourceFiles) {
        # get an array of all filenames (names only) of the files with a similar name already present in the destination folder
        $destFiles = @((Get-ChildItem $DestinationFolder -File -Filter "$($file.BaseName)*$($file.Extension)").Name)
        # for PowerShell version < 3.0 use this
        # $destFiles = @(Get-ChildItem $DestinationFolder -Filter "$baseName*$extension" | Where-Object { !($_.PSIsContainer) } | Select-Object -ExpandProperty Name)

        # construct the new filename
        $newName = $file.Name
        $count = 1
        while ($destFiles -contains $newName) {
            $newName = "{0}({1}){2}" -f $file.BaseName, $count++, $file.Extension
        }
        # use Join-Path to create a FullName for the file
        $newFile = Join-Path -Path $DestinationFolder -ChildPath $newName
        Write-Verbose "Copying '$($file.FullName)' as '$newFile'"

        $file | Copy-Item -Destination $newFile -Force
    }
}

# you can change the folder paths, file pattern to filter etc. here
$destFolder = Join-Path -Path 'D:\Destination' -ChildPath ('{0:yyyy-MM-dd_HH-mm}' -f (Get-Date))
Copy-Unique -SourceFolder "C:\Origin" -DestinationFolder $destFolder -Filter '*.dat' -Recurse -NewerThan (Get-Date).AddMinutes(-300)

When you have saved the above code to let's say 'C:\Scripts\Copy-Unique.ps1' you can then call it from a batch file like:

Powershell.exe -NoLogo -NoProfile -File "C:\Scripts\Copy-Unique.ps1"

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