El Toro Bauldo
El Toro Bauldo

Reputation: 1229

Powershell: subtract $pwd from $file.Fullname

Given the following files:

c:\dev\deploy\file1.txt
c:\dev\deploy\file2.txt
c:\dev\deploy\file3.txt
c:\dev\deploy\lib\do1.dll
c:\dev\deploy\lib\do2.dll

e.g. if $pwd is the following

c:\dev\deploy

running the statement

$files = get-childitem

I want to take this list and using foreach ($file in $files) I want to substitute my own path for the $pwd e.g. I want to print c:\temp\files like the following:

c:\temp\files\file1.txt
c:\temp\files\file2.txt
c:\temp\files\file3.txt
c:\temp\files\lib\do1.dll
c:\temp\files\lib\do2.dll

How can I peform this i.e.

A = c:\dev\deploy\file1.txt - c:\dev\deploy\
B = c:\temp\files\ + A

giving B = c:\temp\files\file1.txt

?

Upvotes: 5

Views: 7574

Answers (5)

Markus Doerig
Markus Doerig

Reputation: 196

The accepted answer only works without Sub-Folders

if you need to "convert" Sub-Folders, the Answer of @stej is better.

Here my Version:

 Get-ChildItem -Recurse | ForEach-Object { $_.Fullname.Replace('D:\Work\Test\Release', 'C:\temp\files') }

Note: .Replace doesn't need to be escaped

Upvotes: 1

Jordij
Jordij

Reputation: 158

There's a cmdlet for that, Split-Path, the -leaf option gives you the file name. There's also Join-Path, so you can try something like this:

dir c:\dev\deploy | % {join-path c:\temp\files (split-path $_ -leaf)} | % { *action_to_take* }

Upvotes: 1

stej
stej

Reputation: 29469

I would use filter here and consider piping the files like this:

filter rebase($from=($pwd.Path), $to)  {
    $_.FullName.Replace($from, $to)
}

You can call it like this:

Get-ChildItem C:\dev\deploy | rebase -from C:\dev\deploy -to C:\temp\files\
Get-ChildItem | rebase -from (Get-Location).path -to C:\temp\files\
Get-ChildItem | rebase -to C:\temp\files\

Note that the replacing is case sensitive.


In case you would need case insensitive replace, regexes would help: (edit based on Keith's comment. Thanks Keith!)

filter cirebase($from=($pwd.Path), $to)  {
    $_.Fullname -replace [regex]::Escape($from), $to
}

Upvotes: 6

Keith Hill
Keith Hill

Reputation: 201892

This works pretty well for me:

gci c:\dev\deploy -r -name | %{"c:\temp\$_"}

Upvotes: 1

tyranid
tyranid

Reputation: 13318

How about something like:

function global:RelativePath
{
    param
    (
        [string]$path = $(throw "Missing: path"),
        [string]$basepath = $(throw "Missing: base path")
    )

    return [system.io.path]::GetFullPath($path).SubString([system.io.path]::GetFullPath($basepath).Length + 1)
}    

$files = get-childitem Desktop\*.*

foreach($f in $files)
{
    $path = join-path "C:\somepath" (RelativePath $f.ToString() $pwd.ToString())
    $path | out-host
}

I took the simple relative path from here although there is some problems with it, but as you only want to handle paths below your working directory it should be okay.

Upvotes: 1

Related Questions