简体   繁体   中英

Copy-Item not including subfolder files of source directory in PowerShell

I have a script which moves files with a specific extension from a source directory to a destination directory.

My source directory looks like:

FILESFOLDER

  • File1.td

  • File2.td

    SUBFOLDER

    • File3.td

    • File4.td

My script is short and looks like:

if(!(Test-Path $SourceDirPath) -or !(Test-Path $DestinationDirPath))
{
    Write-Host "The source- or destination path is incorrect, please check "
    break
}else
{
    Write-Host "Success"
    Copy-Item -path $SourceDirPath -Filter "*$extension" -Destination $DestinationDirPath -Recurse
}

I have to mention that the $SourceDirPath comes from a config file and only works if I declare it as C:\\FILESFOLDER\\*

The script works but doesn't copy the files from the subfolder to destination. The destination only has File1 and File2.

What's wrong with my Copy-Item command?

The -Recurse switch has no effect in your case , because it's only applied to the items matched by the combination of $SourceDirPath , which uses a trailing \\* to match the items in the source directory, and -Filter , which in your case are only the *.td files located directly in your source directory.

Omitting the trailing \\* to target the directory itself (eg, C:\\FOLDER rather than C:\\FOLDER\\* ), solves that problem in principle , but, due to an annoying quirk only works as intended if the destination directory does not exist yet. If it does exist, the items are placed in a subdirectory of the destination directory, named for the source directory.

If there's nothing in the existing destination directory to preserve before copying (and no special attributes of directory itself need preserving, you can work around the problem by deleting the preexisting destination directory beforehand .

if(!(Test-Path $SourceDirPath) -or !(Test-Path $DestinationDirPath))
{
    Write-Host "The source or destination path is incorrect, please check "
    break
}
else
{
    Write-Host "Success"

    # Delete the preexisting destination directory,
    # which is required for the Copy-Item command to work as intended.
    # BE SURE THAT IT IS OK TO DO THIS.
    Remove-Item $DestinationDirPath -Recurse

    # Note: $SourceDirPath must NOT end in \*  
    Copy-Item -Recurse -LiteralPath $SourceDirPath -Filter "*$extension" -Destination $DestinationDirPath
}

If you do need to preserve existing $DestinationDirPath content or attributes (ACLs, ...), more work is needed.

You should use the Get-ChildItem cmdlet with the -recurse parameter to retrieve all files based on your filter condition. Then you can pipe the result to the Copy-Item cmdlet and only have to specify a destination.

So this will compare the directory source versus the destination and then copy over the content. Ignore my funky variables, I've amended them below on a edit

 #Release folder
    $Source =  ""
    #Local folder
    $Destination = ""

    #Find all the objects in the release
    get-childitem $Source -Recurse | foreach {

    $SrcFile = $_.FullName
    $SrcHash = Get-FileHash -Path $SrcFile -Algorithm MD5 # Obtain hash

    $DestFile = $_.Fullname -replace [RegEx]::escape($Source),$Destination #Escape the hash
    Write-Host "comparing $SrcFile to $DestFile" -ForegroundColor Yellow

    if (Test-Path $DestFile) 
    {
    #Check the hash sum of the file copied
    $DestHash = Get-FileHash -Path $DestFile -Algorithm MD5

    #compare them up
    if ($SrcHash.hash -ne $DestHash.hash) {
        Write-Warning "$SrcFile and $DestFile Files don't match!"

        Write-Warning "Copying $SrcFile to $DestFile " 

        Copy-Item $SrcFile -Destination $DestFile -Force
    } 
    else {
        Write-Host "$SrcFile and $DestFile Files Match" -ForegroundColor 
Green

    }
        } 
    else {
        Write-host "$SrcFile is missing! Copying in" -ForegroundColor Red
        Copy-Item $SrcFile -Destination $DestFile -Force

         }
    }  

Try this:

$source =  "C:\Folder1"

$destination = "C:\Folder2"

$allfiles = Get-ChildItem -Path $source -Recurse -Filter "*$extension"
foreach ($file in $allfiles){
    if (test-path ($file.FullName.replace($source,$destination))) {
    Write-Output "Seccess"
    Copy-Item -path $file.FullName -Destination ($file.FullName.replace($source,$destination))
    }
    else {
    Write-Output "The source- or destination path is incorrect, please check "
    break
    }
}

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