splitting path using powershell

This topic contains 4 replies, has 4 voices, and was last updated by Profile photo of Richard Siddaway Richard Siddaway 3 years, 1 month ago.

  • Author
    Posts
  • #15233
    Profile photo of Avikal Jain
    Avikal Jain
    Participant

    Hello experts,

    I am new to powershell and I am writing a powershell script to copy certain files from temp location to target directories, this is where I am right now:

    $sourcedirectory = "C:\temp\Source"
    $targetdirectory = "C:\Users\Dest"
    $backupdirectory = "C:\Users\Dest\"
    #get-location
    #cd $sourcedirectory
    #get-location
    #Get-ChildItem -recurse | where {$_.PsIsContainer} | Select-Object Name
    #dir -r | % { if ($_.PsIsContainer) {$_.Name} }
    #Resolve-Path -relative

    if (!(Test-Path -path $targetdirectory)) {New-Item $targetdirectory -Type Directory}
    #Take back up of existing file
    $backup_directory = New-Item -Path "$backupdirectory\backup_$(Get-Date -Format yyyyMMdd)" -Force -ItemType Directory
    Write-Host Copying contents from $targetdirectory to $backup_directory
    Copy-Item -Path $targetdirectory -recurse -Destination "$($backup_directory.Fullname)" -Force

    #Copy files from source to destination
    #Write-Host Following files needs to be copied:

    $absolutePath = Get-ChildItem -Path $sourcedirectory -recurse
    foreach ($item in $absolutePath)
    {
    Write-Host Copying $item.FullName to $targetdirectory
    Copy-Item -Path $sourcedirectory/* -recurse -force -Destination $targetdirectory
    }

    My directory structure at source looks like below:
    Source\
    +-Client\
    +-bin\
    +-ext\
    +-ext64\
    +-lib\
    +-Patches\
    +-Server\
    +-ext\
    +-ext64\
    +-Patches\

    On Dest, same folder structure is available as well.

    Using powershell command i just want the output like below:
    \Source\Client\bin
    \Source\Client\ext
    \Source\Client\patches....

    \Source\Server\ext
    \Source\Server\ext24
    \Source\Server\patches
    The Get-ChildItems commands I have tried so far gives me the absolute path, i want output to be listed in above manner i.e remove C:\temp from the output. I will use this in my for loop for a proper message as stdout here:

    Write-Host Copying $item.FullName to $targetdirectory\

    Also, please let me know if script looks ok altogether or not.

  • #15239
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    First off think about using Write-verbose rather than Write-Host. You probably need quotes round the message you are writing.

    There is no straightforward way to remove the c:\temp part of the path

    You can remove the c: using split-path with the -NoQualifier parameter which outputs a string. You could use something like this

    get-childitem C:\Temp -Filter *.xml | select fullname | Split-Path -NoQualifier | foreach{$_.Replace("\Temp","")}

    but its very ugly

  • #15240
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    You could do something like this to trim "c:\temp" from the beginning of the strings:

    function Remove-LeadingString
    {
        [CmdletBinding()]
        param (
            [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
            [AllowEmptyString()]
            [string[]]
            $String,
    
            [Parameter(Mandatory = $true)]
            [string]
            $LeadingString
        )
    
        process
        {
            foreach ($s in $String)
            {
                if ($s.StartsWith($LeadingString, $true, [System.Globalization.CultureInfo]::InvariantCulture))
                {
                    $s.Substring($LeadingString.Length)
                }
                else
                {
                    $s
                }
            }
        }
    }
    
    $paths = @(
        'C:\Temp\Testing 123'
        '\Something\Else'
        'c:\temp\whatever\subfolder'
    )
    
    $paths | Remove-LeadingString -LeadingString 'C:\temp'
    

    If you don't mind regular expressions and don't need the pipeline support, you don't even need a function. You can just use the -replace operator:

    $paths = @(
        'C:\Temp\Testing 123'
        '\Something\Else'
        'c:\temp\whatever\subfolder'
    )
    
    $paths -replace '^c:\\temp'
    
  • #15251
    Profile photo of Joakim
    Joakim
    Participant

    In addition to what has already been suggested, maybe you could benefit from something like this:

    $pathParts = $path.Split([system.io.path]::DirectorySeparatorChar)

    That would put the different parts of your sourcepath in the array $pathParts. Lets say you have four parts to your path, and you don't want the first bit. Then you can simply use this as follows (the array is zero based):

    Copy-Item $sourcefile [System.IO.Path]::Combine( $pathParts[1], $pathParts[2], $pathParts[3])

    This example is taking advantage of the .NET Framework System.Path object. It is a lot safer to add paths together using Path.Combine!

  • #15252
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    You could also use Join-Path to create the destination

You must be logged in to reply to this topic.