0

I've been working on this one issue for abut a week, and think I'm missing something obvious...I need a couple sets of eyes.

Starting with this question I researched all the links provided in the answer, and I'm running the following script, gleaned from MS Connect:

$txtPath = "c:\users\xxxxxx\desktop\cgc\tx"
$txtPath2 = "c:\users\xxxxxx\desktop\cgc\tx2"
get-childitem $txtPath | foreach {  
    Move-Item -literalpath $txtPath2.Name $_.Name.Replace ("]" | "[", "_") 
}

Both paths exist. *\tx contains 35 *.txt files, some with square brackets in the name, some without. *\tx2 is currently empty, awaiting output files from the script.

If I've written my third statement properly, I'm passing each child from \tx to the function where square brackets are changed to an underscore as the file is moved and re-saved to the new location, \tx2.

Unfortunately, I get this error:

Expressions are only allowed as the first element of a pipeline.
At C:\users\xxxxxx\desktop\cgc\rni.ps1:4 char:71
+     Move-Item -literalpath $txtPath2.Name $_.Name.Replace ("]" | "[", "_" <<<< )
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : ExpressionsMustBeFirstInPipeline

If I'm interpreting the error correctly, something's preventing the close paren to be recognized. Do I need some kind of escape character for the brackets? I tried using a backtick escape and backslash escape inside the quotes, but that led to the same error.

With the escape outside the quotes, I got this error.

The term '\]' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling
 of the name, or if a path was included, verify that the path is correct and try again.
At C:\users\xxxxxx\desktop\cgc\rni.ps1:4 char:61
+     Move-Item -literalpath $txtPath2.Name $_.Name.Replace (\"]" <<<<  | \"[", "_")
    + CategoryInfo          : ObjectNotFound: (\]:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

What am I missing?

Community
  • 1
  • 1
dwwilson66
  • 6,806
  • 27
  • 72
  • 117

1 Answers1

3

You got the syntax wrong:

$_.Name.Replace ("]" | "[", "_")

is just nonsense. Usually it would mean “Call the Replace method on $_.Name with the return value of the following as argument: Pipe the string ']' as input into the command '[', '_'. But here lies the first problem: That's no command, it's an expression and that cannot work. Then the problem is that this is the argument to a cmdlet. Special rules apply here and they usually say “convert to string everything that isn't in parentheses”. So there isn't even a method call, you'd get the method declaration as the new file name and pass another argument that suffers from the problems described above.

If I'd have to guess I'd think you want to replace square brackets by underscores. If so, then use the following:

Move-Item -literalpath $txtPath2.Name ($_.Name -replace '\[|]', '_') 
Joey
  • 344,408
  • 85
  • 689
  • 683
  • Tried the backtick when backslash errored out...grasping at straws... Now, I was under the impression that inside the quotes, I could use | as an OR...in my case above, looking for [ or ] to replace. You use that in your second example. So that would suggest that the DOUBLE quotes were my biggest issue; should have been singles. Am I thinking about this right? – dwwilson66 Jan 30 '13 at 15:17
  • You are confusing the string .replace() method with the Powershell -replace operator. They are not the same. – mjolinor Jan 30 '13 at 15:24
  • @Joey For your .Replace command: Help me understand the syntax. I thought that the replace syntax as (oldValue,newValue). Are you missing a paren after the ]? if not, does PS just parse the LAST value as the new value for any of the preceding strings? – dwwilson66 Jan 30 '13 at 15:24
  • And no, you're not. The quotes are actually irrelevant here (not always, though – I just tend to use single quotes when I don't need the double-quote functionality), but you didn't quote the `|`. It was outside of any quotes and thus part of the language syntax. Things went weird at that point. You can use regular expressions with the `-replace` operator, so you can use `|` there (but within a string!). `string.Replace` though only replaces literal strings or characters so using `|` there would be wrong, too. – Joey Jan 30 '13 at 15:26
  • @Joey - Why on earth would I Invoke-Expression? Even iex is three more keystrokes than simply keying foo.ps1. Or F3 when I'm debugging. :) – dwwilson66 Jan 30 '13 at 15:27
  • @Joey - one more clarification. I was using Move-Item because -literalpath is not a recognized parameter in PS2.0 https://connect.microsoft.com/PowerShell/feedback/details/277707/rename-item-fails-when-renaming-a-file-and-the-filename-contains-brackets. Assuming everything else is syntactically correct, though.... – dwwilson66 Jan 30 '13 at 15:33
  • I've rewritten the answer by now to be less snarky (sorry for that) and perhaps a little bit more helpful. The initial code was slightly wrong (at least the `.Replace` part). – Joey Jan 30 '13 at 15:35
  • Ah, sorry for the `Rename-Item`. I have to admit, I never stumbled over that since I rarely, if ever, do filesystem stuff in PowerShell. I use it mostly as a scripting language, not as a shell or administrative tool ;). And the `iex` is quite common if you run *native* programs (not cmdlets) where argument passing can be weird at best and broken at worst. Some people try everything and often end up with a question here on SO where they wrapped it in `iex` and `&'...'` and whatnot. All those layers don't make the problem disappear, of course :-) – Joey Jan 30 '13 at 15:38
  • @Joey Snark keeps me humble. :) Watch for the next snark-worthy question--that script you just helped with is deleting the destination path. That's a headscratcher. Oy. – dwwilson66 Jan 30 '13 at 16:03