Question

Can someone tell me why this script won't work?

Get-ChildItem "\\fhnsrv01\home\aborgetti\Documentation\Stage" -Filter *.EDIPROD | `
Foreach-Object{
    $content = Get-Content $_.FullName

    #filter and save content to a new file 
    $content | Where-Object {$_ -match 'T042456'} | Rename-Item `
                                                         ($_.BaseName+'_834.txt')

I found this syntax from another question on here and changed the environment variables.

For some reason it won't change the name of the file. The filename is

'AIDOCCAI.D051414.T042456.MO.EDIPROD'

Help much appreciated.

UPDATE

Thanks to TheMadTechnician I was able to get some working stuff. Great stuff actually. Figure I should share with the world!

#Call Bluezone to do file transfer
#start-process "\\fhnsrv01\home\aborgetti\Documentation\Projects\Automation\OpenBZ.bat"
#Variable Declarations
$a = Get-Date
$b = $a.ToString('MMddyy')
$source = "\\fhnsrv01\home\aborgetti\Documentation\Stage\"
$dest = "\\fhnsrv01\home\aborgetti\Documentation\Stage\orig"
#Find all the files that have EDIPROD extension and proceed to process them
#First copy the original file to the orig folder before any manipulation takes place
Copy-item $source\*.EDIPROD $dest
# Now we must rename the items that are in the table
Switch(GCI \\fhnsrv01\home\aborgetti\Documentation\Stage\*.EDIPROD){
    {(GC $_|Select -first 1) -match "834*"}{$_ | Rename-Item -NewName {$_.BaseName+'_834.txt'}}
    {(GC $_|Select -first 1) -match "820*"}{$_ | Rename-Item -NewName {$_.BaseName+'_820.txt'}}
}
Was it helpful?

Solution

Get-ChildItem's -Filter has issues, I really hesitate to use it in general. If it were up to me I'd do something like this:

Get-ChildItem "\\fhnsrv01\home\aborgetti\Documentation\Stage" |
    ?{$_.Extension -match ".EDIPROD" -and $_.name -match "T042456"}|
    %{$_.MoveTo($_.FullName+"_834.txt")}

Well, I would put it all on one line, but you can line break after the pipe and it does make it a little easier to read, so there you have it. I'm rambling, sorry.

Edit: Wow, I didn't even address what was wrong with your script. Sorry, kind of distracted at the end of my work day here. So, why doesn't your script work? Here's why:

You pull a file and folder listing for the chosen path. That's great, it should work, more or less, I have almost no faith in the -Filter capabilities of the file system provider, but anyway, moving on!

You take that list and run it through a ForEach loop processing each file that matches your filter as such:

  1. You read the contents of the file, and store them in the variable $content
  2. You run the contents of the file, line by line, there a Where filter looking for the text "T042456"
  3. For each line that matches that text you attempt to rename something to that line's basename plus _834.txt (the line of text is a string, it doesn't have a basename property, and it's not an object that can be renamed, so this is going to fail)

So, that's where the issue is. You're pulling the contents of the file, and parsing that line by line trying to match the text instead of matching against the file name. If you removed Everything after the first pipe up to the Where statement, and then for your rename-item put -newname before your desired name, and change the ( ) to { } that goes around the new name, and you would be set. Your code would work. So, your code, modified as I said, would look like:

Get-ChildItem "\\fhnsrv01\home\aborgetti\Documentation\Stage" -Filter *.EDIPROD | 
    Where-Object {$_ -match 'T042456'} | Rename-Item -NewName {$_.BaseName+'_834.txt'}

Though I have a feeling you want $.Name and not $.BaseName. Using $_.BaseName will leave you with (to use your example file name):

'AIDOCCAI.D051414.T042456.MO_834.txt`

Edit2: Really that's a whole different question, how to match multiple criteria, but the question is here, I'm here, why not just get it done?

So, you have multiple criteria for matching the file names. That really doesn't affect your loop to be honest, what it does affect is the Where statement. If you have multiple options what you probably want is a RegEx match. Totally doable! I'm only going to address the Where statement (?{ }) here, this won't change anything else in the script.

We leave the extension part, but we're going to need to modify the file name part. With RegEx you can match against alternative text by putting it in parenthesis and splitting up the various options with a pipe character. So it would look something like this:

"(T042456|T195917|T048585)"

Now we can incorporate that into the rest of the Where statement and it looks like this:

?{$_.Extension -match ".EDIPROD" -and $_.name -match "(T042456|T195917|T048585)"}

or in your script:

Where-Object {$_ -match "(T042456|T195917|T048585)"}

Edit3: Hm, need the first line for the qualifier. That complicates things a bit. Ok, so what I'm thinking is to get our directory listing, get the first line of each file with the desired extension, make an object that has two properties, the first property is the fileinfo object for the file, and the other property will be the first line of the file. Wait, I think we can do better. Switch (GCI *.EDIPROD){(get-content|select -first 1) -match 820}{Rename 820};{blah blah -match 834}{rename 834}}. Yeah, that should work. Ok, actual script, not theoretical gibberish script time. This way if you have other things to look for you can just add lines for them.

Switch(GCI \\fhnsrv01\home\aborgetti\Documentation\Stage\*.EDIPROD){
    {(GC $_|Select -first 1).substring(177) -match "^834"}{$_ | Rename-Item -NewName {"834Dailyin$b"};Continue}
    {(GC $_|Select -first 1).substring(177) -match "^820"}{$_ | Rename-Item -NewName {$_.BaseName+'_820.txt'};Continue}
}

Again, if you want the EDIPROD part to remain in the file name change $_.BaseName to $_.Name. Switch is pretty awesome if you're trying to match against different things and perform different actions depending on what the results are. If you aren't familiar with it you may want to go flex your google muscles and check it out.

Hm, alternatively we could have gotten the first line inside the Where filter, run a regex match against that, and renamed the file based on the regex match.

GCI \\fhnsrv01\home\aborgetti\Documentation\Stage\*.EDIPROD | ?{(GC $_ | Select -First 1) -match "(820|834)"}|Rename-Item -NewName {$_.Name+"_"+$Matches[1]+".txt"}

Then you just have to update the Where statement to include anything you're trying to match against. That's kind of sexy, though not as versatile as the switch. But for just simple search and rename it works fine.

OTHER TIPS

Try it like this way

Get-ChildItem -Filter "*T042456*" -Recurse | % {Rename-Item $_ "$_ _834.txt"}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top