9

Calling this powershell command and getting an error. Driving me nuts.

Prompt> get-childitem -recurse ./ *NYCSCA* |  where-object { $_.Name -like
 "*NYCSCA*" } |  rename-item $_ -newname $_.Name.Replace(" ","_") -whatif

Here is the response:

You cannot call a method on a null-valued expression.
At line:1 char:140
+ get-childitem -recurse ./ *NYCSCA* |  where-object { $_.Name -like "*NYCSCA*" } | select FullName | rename-item $_ -n
ewname $_.Name.Replace <<<< (" ","_") -whatif
    + CategoryInfo          : InvalidOperation: (Replace:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

If I remove the last part, I get a list of files. Any clues? I have not grocked powershell yet, obviously.

Note: I tried to post this to superuser, but the site is consistently failing now - won't let me add this exact question.

Here it is greatly simplified. I cannot even get this classic example to work.

gci  *NYCSCA*  | ren $_ ($_.Name).Replace("foo","bar")

Thank you @JNK, the % did it. The solution I needed is this, in case you're interested:

gci -recurse | where-object{ $_.Name -like "*NYCSCA*"} | %{rename-item $_.FullName $_.FullName.Replace("NYCSCA","SDUSD") }
Daniel Williams
  • 8,912
  • 15
  • 68
  • 107

2 Answers2

8

I think you need foreach-object:

get-childitem -recurse ./ *NYCSCA* |  where-object { $_.Name -like
 "*NYCSCA*" } | % {rename-item $_ -newname $_.Name.Replace(" ","_") -whatif}

The piped array can't be renamed as a set.

JNK
  • 63,321
  • 15
  • 122
  • 138
  • Yes! That is it - thank you. I need to understand sets versus items better. But this is great! – Daniel Williams Aug 24 '11 at 20:47
  • Glad it helped. My first step anytime I have a pipe not work is to try a foreach-object. – JNK Aug 24 '11 at 20:48
  • 1
    When powershell drops down into a folder to do the renaming there it complains that the file doesn't exist. How could I solve that building off your example? – The Muffin Man Jul 29 '14 at 03:16
  • @TheMuffinMan I would post a new question about it. It's probably related to the exact syntax you're using. – JNK Jul 29 '14 at 12:10
  • This command doesn't seem to work right with subdirectories as @TheMuffinMan reported. See http://stackoverflow.com/a/21614001/8479 instead. – Rory May 15 '16 at 21:03
5

Here's a simplified version to rename files only

Get-ChildItem -Filter *NYCSCA* -Recurse |
 Where-Object {!$_.PSIsContainer} | 
 Rename-Item -NewName { $_.Name.Replace(' ','_') } -WhatIf

(Edit: line breaks added for clarity)

Richard
  • 106,783
  • 21
  • 203
  • 265
Shay Levy
  • 121,444
  • 32
  • 184
  • 206
  • 1
    The real difference here is using code blocks `{...}` in `rename-item` arguments to allow reference to `$_` (which is why `foreach-object` also provides a solution. – Richard Aug 25 '11 at 09:45
  • True, foreach-object does the job but it adds overhead (and is slower). – Shay Levy Aug 25 '11 at 09:59
  • Interesting, so this lets rename-item treat its arguments as a set, rather than having rename-items called within a set of operations of the foreach. – Daniel Williams Aug 25 '11 at 14:32