Powershell get full filepath using Get-ChildItem

99 views Asked by At

I am new to powershell and using it as a one off to help me extract some files I've collected during my experiments.

I have many data sets with nested subfolders of processed data. They all have a folder in the path called "VPP" and I want to extract only the files in this folder and copy them to a new location. I want to do this while preserving the existing directory structure, so the parent folders will all be empty but the directory structure will be preserved. I need it like this so that I can preserve the organisation of the data (since I identify datasets from the parent folder name at the top of the tree) and so that I can copy files back to the original folder at a later date and have them end up in the right place.

So far, I have adapted a script I found online:

$sourceDirectory = "F:\OneDrive - University of Edinburgh\PhD\Results\Campaign1_Part4\GustData"
$destDirectory = "C:\Users\Anjali\Desktop\test"    
$keyword = "VPP"
$children = Get-ChildItem -Path $sourceDirectory -Recurse

foreach ($child in $children)
{
    if ($child -match $keyword)
    {
        try
        {                               
            Copy-Item -Path "$($sourceDirectory)\$($child )" -Destination $destDirectory -Force -Recurse
        }
        catch [System.Exception] 
        {
            Write-Output $_.Exception
        }
    }
}

The problem I have is that the $child variables are only the filename and do not have any of the intermediate subfolders. I want $child to be the file path starting from $sourceDirectory e.g. "dataset1\folderA\folderB\VPP\file1" but it's coming out "file1".

How do I retrieve the intermediate filepath?

2

There are 2 answers

1
lit On

This will copy the VPP directories to a new location while maintaining the directory structure.

When you are confident that the correct directories will be copied, remove the -WhatIf switch from the Copy-Item command.

Note, this code will remove all files under the destination directory before copying. This is to ensure that no stray. extraneous files are left lying around. You may want to change that.

You will need to change the first line specifying the source directory.

$sourceDirectory = 'C:\src\t\so\78211086\'
$destDirectory = Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop' -AdditionalChildPath 'test'
$keyword = 'VPP'

# Set the current directory to the source directory for Resolve-Path.
Push-Location $sourceDirectory

# Remove any existing data set directory and create it anew.
if (Test-Path -Path $destDirectory) { Remove-Item -Recurse -Force $destDirectory }
New-Item -ItemType Directory -Path $destDirectory | Out-Null

Get-ChildItem -Recurse -Directory -Filter $keyword | ForEach-Object {
    $VppPath = Resolve-Path -Path $_.FullName -Relative
    $DestinationPath = Join-Path -Path $destDirectory -ChildPath $VppPath
    Copy-Item -Recurse -Path $VppPath -Destination $DestinationPath -WhatIf
}

# Return to whatever the directory was before this started.
Pop-Location

Show the contents of the destination directory with the following command.

Get-ChildItem -Recurse $destDirectory | Select-Object -Property FullName
0
Theo On

You could also do this without changing the current location like below:

$sourceDirectory = 'F:\OneDrive - University of Edinburgh\PhD\Results\Campaign1_Part4\GustData'
$destDirectory   = 'C:\Users\Anjali\Desktop\test'
$keyword         = 'VPP'

Get-ChildItem -Path $sourceDirectory -Directory -Recurse -Filter $keyword | ForEach-Object {
    # construct the destination folder path
    $targetPath = Join-Path -Path $destDirectory -ChildPath $_.FullName.Substring($sourceDirectory.Length)
    # create the target destination folder if this does not already exist
    $null = New-Item -Path $targetPath -ItemType Directory -Force
    $_ | Copy-Item -Destination $targetPath -Recurse -Force
}