Read first line of text in txt file them cut charters 5-10 to a variable

This topic contains 37 replies, has 4 voices, and was last updated by Profile photo of Nathan W Nathan W 1 year, 7 months ago.

  • Author
    Posts
  • #32391
    Profile photo of Nathan W
    Nathan W
    Participant

    I am working on a script that will read the first line of text in a txt file then take that line and cut charters 5 through 15 and then out those cut charters into a variable to use later.
    I am thinking that Get-Content is the way to go but having a hard time with the cut to variable part.

    Thanks!!

  • #32392
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    $var = Get-Content -Path C:\temp\testfile.txt
    $var2 = $var.Substring(5,15)
    $var2[0]

    I think 😀
    you may have to index [0] if there are multiple lines

    $var2[0]

  • #32393
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    You are not limiting your content to the first line so $var is actually an array of lines from the input file. substring does not work on arrays. You need to limit to the first line of the file content. Easy way is to use select-object.

    $var = Get-Content -Path C:\temp\testfile.txt | Select-Object -First 1
    $var.Substring(5,15)
    
  • #32394
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    yup I realized that thanks Curtis you always teach me something new.

  • #32395
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    Ah you got an edit in there while I was posting. Using the array position will work, but that means you have to load the full content of the file. Using Select-Object, it will stop reading the file after the select criteria has been met.

  • #32396
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    Tag, you're it 🙂

  • #32397
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    If you use that method, your array position should be defined on your input file variable "$var". It holds the array that has the content of the file.

    $var = Get-Content -Path C:\temp\testfile.txt
    $var2 = $var[0].Substring(5,15)
    $var2
    
  • #32398
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    well I knew about select-object -first but did not know it would select the first line. At first I thought get-content would treat the file as one big text string did not know new lines would be treated as objects. I love this stuff you just keep on learning new things.

  • #32399
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    lol I was trying to do that but I was doing this $var2 = $var.Substring(5,15)[0]

    one of those times I was writing the code in the chat window rather then using powershell.

  • #32409
    Profile photo of Nathan W
    Nathan W
    Participant

    I sense I am making a mess of this.
    Here is my code so far

    $FileLocation = "D:\Files"
    
    $File1Temp = Get-ChildItem $FileLocation -Filter File1.txt.*
    $File2Temp = Get-ChildItem $FileLocation -Filter File2.txt.*
    $File3Temp = Get-ChildItem $FileLocation -Filter File3.txt.*
    
    $File1ProcDate = Get-Content -Path "$FileLocation\$File1Temp" -TotalCount 1
    $File1Rem = $File1ProcDate.Substring(32,39)
    Rename-Item -Path "$FileLocation\$File1Temp" File1.txt.$File1Rem"
    $File2ProcDate = Get-Content -Path "$FileLocation\$File2Temp" -TotalCount 1
    $File2Rem = $File2ProcDate.Substring(43,50)
    Rename-Item -path "$FileLocation\$File2Temp" "File2.txt.$File2Rem"
    $File3ProcDate = Get-Content -Path "$FileLocation\$File3Temp" -TotalCount 1
    $File3Rem = $File3ProcDate.Substring(31,38)
    Rename-Item -Path "$FileLocation\$File3Temp" "File3.txt.$File3Rem"
    

    Basicly what I am trying to accomplish is I have a folder where 3 files are sent to with a random number appended top the file name. I am trying to replace that random number with the files processing date which is found with in the first line of text.

    Many thinks for the help!!!!!

  • #32414
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    Nathan, can your add the pre and /pre tags around your code so it can be more easily read and worked with?

  • #32415
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    I can fix it for you when I get to work tomorrow. For the rename look at split-path or look at the properties of the variable when you assign it will be something like $file1temp.filename you can the do a simple rename

  • #32417
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    Quick question. What is the format of the date in the TXT file? Frequently it will contain invalid characters for file names such as the / character or the : character. You will need to remove or replace invalid characters before your rename can occur.

  • #32427
    Profile photo of Nathan W
    Nathan W
    Participant

    the date is just in a string of numbers. Example: 20151130

    Thanks a bunch!!

  • #32471
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    If the date is in the same location in each files this will do all three. However it may hit on some unwanted files I have not learned yet how to add regex but this is the pattern for
    (File)[1-3](\.txt)

    $FileLocation = "D:\Files"
    
    $FileTemp = Get-ChildItem -Path $FileLocation | ?{$_ -like "File*"}
    
    foreach($File in $FileTemp){
    $FileProcDate = Get-Content -Path $File.FullName -First 1
    $FileRem = $FileProcDate.Substring(5,15)
    Rename-Item -Path $File.FullName  (Join-Path $FileLocation "$($FileRem)File1.txt")
    }
    
    
  • #32473
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    Good example Mark

    Here is how you can do it when the date is in a different position for each numbered file. One thing to note in Nathan's code is the use of substring was not correct. Substring takes a starting position and then a number of characters from the starting position, not a starting position then an ending position. As such to get a date that starts at position 32 and is 8 characters long, you should use .substring(32,8), not .substring(32,39)

    $FileLocation = "D:\Files"
    
    Get-ChildItem $FileLocation | 
    Where-Object {$_.name -match "File[123]\.txt\..*"} |
    ForEach-Object {
        Switch ($_.name[4]) {
            1 {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(32,8) } }
            2 {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(43,8) } }
            3 {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(31,8) } }
        }
        [PSCustomObject]@{'Was' = $($_.Name); 'Now' = $($_.Name -replace "\.\w*$", ".$Date")}
        Rename-Item -Path $_.FullName -NewName $($_.Name -replace "\.\w*$", ".$Date")
    }
    

    Results:

    Was                        Now               
    ---                        ---               
    File2.txt.2546367          File2.txt.20151014
    File3.txt.asdgfq4er4yw4589 File3.txt.20150123
    File1.txt.sadlkfjasdf      File1.txt.20140923
    
  • #32474
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    Ah so you can put your regex in the quotations. I did not know that would work. When I tried that the text in the brackets turned green like I was casting something so I gave up.

  • #32475
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    Also, you were using the -like operator. It does not use regex. -match does.

  • #32476
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    Hah that makes sense you wouldn't say like this pattern.. Match this pattern. I wish you sat next to me at work I would pick your brain all day.

  • #32477
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    or -notmatch this pattern. You got it.

  • #32493
    Profile photo of Nathan W
    Nathan W
    Participant

    This looks great.
    Thanks!!!

    One quick question.
    the 3 files I am dealing with have a little different naming convention. Sorry I was a little too genaric on my sample script.
    The 3 files are more like
    FileP.txt.1234567
    FileD.txt.1234567
    FileR.txt.1234567

    So this is how I am thinking to update the script

    Get-ChildItem $FileLocation | 
    Where-Object {$_.name -match "File[PDR]\.txt\..*"} |
    ForEach-Object {
        Switch ($_.name[4]) {
            P {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(32,8) } }
            D {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(43,8) } }
            R {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(31,8) } }
        }
        [PSCustomObject]@{'Was' = $($_.Name); 'Now' = $($_.Name -replace "\.\w*$", ".$Date")}
        Rename-Item -Path $_.FullName -NewName $($_.Name -replace "\.\w*$", ".$Date")
    }
    
  • #32495
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    That looks good. You can also remove the [pscustomobject] line if you like. I just put it there to see some output in the console whil testing.

  • #32499
    Profile photo of Nathan W
    Nathan W
    Participant

    Getting this error when I run the script

    Get-Content : Cannot bind argument to parameter 'Path' because it is null.

    Thanks!!

  • #32500
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    looks like it did not find matches based on the path and or file names check the path variable and the file names to insure the regex is looking for the right file

  • #32509
    Profile photo of Nathan W
    Nathan W
    Participant

    Here is my code but still getting the error.

    $FileLocation = "D:\Files"
    
    Get-ChildItem $FileLocation | 
    Where-Object {$_.name -match "File[PDR]\.txt\..*"} |
    ForEach-Object {
        Switch -regex ($_.name[4]) {
            "P" {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(32,8) } }
            "D" {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(43,8) } }
            "R" {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(31,8) } }
        }
        [PSCustomObject]@{'Was' = $($_.Name); 'Now' = $($_.Name -replace "\.\w*$", ".$Date")}
        Rename-Item -Path $_.FullName -NewName $($_.Name -replace "\.\w*$", ".$Date")
    }
    
  • #32515
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    It appears you may be running an out dated version of PowerShell. The code works perfectly for me in PoSh 3.0 and 4.0, but gives your error in 2.0. You should upgrade.

  • #32518
    Profile photo of Nathan W
    Nathan W
    Participant

    Ahh. If upgrading where only an option 😉

  • #32519
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    Ok then, here is a workaround that is PoSh 2.0 compatible.

    $FileLocation = "D:\Files"
    
    Get-ChildItem $FileLocation | 
    Where-Object {$_.name -match "File[PDR]\.txt\..*"} |
    ForEach-Object {
        $input = $_
        Switch -regex ($_.name[4]) {
            "P" {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(32,8) } }
            "D" {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(43,8) } }
            "R" {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(31,8) } }
        }
        New-Object -Type PSObject -Property @{'Was' = $($_.Name); 'Now' = $($_.Name -replace "\.\w*$", ".$Date")}
        Rename-Item -Path $_.FullName -NewName $($_.Name -replace "\.\w*$", ".$Date")
    }
    
  • #32525
    Profile photo of Nathan W
    Nathan W
    Participant

    This is really close.
    It is working for the FileD but it is using the same bit of code for the other 2 files.

    Any suggestions?

    Thanks!!!

  • #32526
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    The switch is looking at the 5th character in the file names could it be a case issue? Unless the $date variable is no being set after the first pass.

    Clear the $date variable after the foreach

    ForEach-Object {
    $date = $null

    If it still sets the date the same then it is selecting switch D for each pass

  • #32527
    Profile photo of Cam Evenson
    Cam Evenson
    Participant

    Never mind..

  • #32528
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    Cam, you should start a separate post.

  • #32529
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    Nathan, can you give some actual examples of the 3 file names and the first line of each file?

  • #32539
    Profile photo of Nathan W
    Nathan W
    Participant

    Due to the project I am working on I can't give exact names of these files but I can say the each file has the same number of charters.
    XXXXXXXP.txt.12345678912345678
    XXXXXXXD.txt.12345678912345678
    XXXXXXXR.txt.12345678912345678

    Thanks so much for the help. The Powershell Community is one of the best there is 🙂

  • #32540
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    is the XXXXXXX the same name for all files how many characters is the XXXXXXX

  • #32544
    Profile photo of Nathan W
    Nathan W
    Participant

    It is the same. Each X represents one of the characters of the file name.
    The P, D and R are the non common characters and the charaters following the txt. are a time stemp for when the fire was created.

    Thanks

  • #32545
    Profile photo of Mark Hammonds
    Mark Hammonds
    Participant

    the 4 in his Switch is looking at the PDR in your file 5th character if your actual file has seven characters before the PDR you need to change the number to 7. Chances are your 5th character in all your file names is a D and that is why it is selecting that switch for every file

    $FileLocation = "D:\Files"
    
    Get-ChildItem $FileLocation | 
    Where-Object {$_.name -match "File[PDR]\.txt\..*"} |
    ForEach-Object {
        $input = $_
        Switch -regex ($_.name[7]) {
            "P" {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(32,8) } }
            "D" {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(43,8) } }
            "R" {$Date = Get-Content -Path $input.FullName -TotalCount 1 | ForEach-Object { $_.Substring(31,8) } }
        }
        New-Object -Type PSObject -Property @{'Was' = $($_.Name); 'Now' = $($_.Name -replace "\.\w*$", ".$Date")}
        Rename-Item -Path $_.FullName -NewName $($_.Name -replace "\.\w*$", ".$Date")
    }
    
    
  • #32552
    Profile photo of Nathan W
    Nathan W
    Participant

    Perfection!!!!!

    THANKS!!!!!!!!!

You must be logged in to reply to this topic.