tags:

views:

1224

answers:

2

I'm a PowerShell novice, and I'd love to be able to script this. I have a text file where each line is part of a file name without the path or extension. I'd like a one-liner that loops through each line of the file (with a gc - Get-Content, right?), takes the content of the line, constructs the source path (the network drive and extension are static), constructs a destination path, and then copies each file. My file content is like this:

12345678
98765432
32145698
12365782

And my source folder is a UNC path like this:

\\server\share

And my destination folder is:

c:\temp\files

I would like to do the equivalent of this DOS command, using $_ as the text from each line of the file:

copy \\server\share\$_.ext c:\temp\files\$_.ext

I'm pretty sure I can use gc and $_ to access each line of the file, and that I need to use cp to copy the files, but I'm having trouble constructing the source and destination file names.

+2  A: 

Try the following

gc theFileName | 
  %{ "{0}.ext" -f $_ } |
  %{ copy "\\server\share\$_" "c:\temp\files\$_" }

It can actually be done on one line but it looks better formmated as multiple lines for this answer :)

JaredPar
Excellent. Thanks very much! @JaredPar, my personal Powershell coach.
AJ
anything wrong with `gc theFileName | %{ cp '\\server\share\$_.ext' 'C:\temp\files' }`? Or would that betoo short? :-)
Joey
@Johannes, I *think* that will work but I forget the parsing rules on replacement within a string occasionally and wasn't sure if the .ext would be interpretd correctly. Hence went the safe route
JaredPar
Johannes, watch out for the single quotes. Those won't expand $_.
Keith Hill
+3  A: 

Copy-Item can take a script block directly in this case so the Foreach-Object stages are unnecessary:

gc theFileName | cpi -l {"\\server\share\$_.exe"} c:\temp\files -whatif

Remove the -WhatIf parameter once you're satisfied it works. The -l is short for -LiteralPath which helps PowerShell determine which parameterset is in use. Also better to use literal path here so that wildcard characters don't get globbed (unless you want that - if so then use -path).

Essentially pipeline bound parameters can be specified via scriptblocks and PowerShell will attempt to resolve the result of the scriptblock to the type expected by the pipeline bound parameter.

Keith Hill
Is this true in general or a nifty feature of Copy-Item?
Richard Berg
This works for any parameter that is also pipeline bound. The PowerShell parameter parser/binder will eval the script block for pipeline bound parameters unless, of course, the parameter type is [scriptblock].
Keith Hill
Indeed, it even works on ValueFromPipelineByPropertyName params -- awesome!
Richard Berg
Nope, nevermind, not as cool as I expected. Your syntax does not *transform* the property that's attached to the pipeline object -- it *overwrites* it. Still handy for one-off cases but far less useful in general.
Richard Berg