Parsing non-standard files for text using PowerShell and Select-String - file

Microsoft Remote Desktop saved sessions have values in them when you open them with a text editor (to test yourself, open Remote Desktop Connection, click Options, and then click Save As. Open the resulting .rdp file in a text editor).
However, using the standard Select-String command here (which works when exactly the same syntax on other file formats):
$MyOObject."Prompt" = (Select-String -Path $Path -Pattern "promptcredentialonce: (.*)").Matches.Groups[1].Value
... produces the following error:
Cannot index a null array
Is there a different command to use to parse this kind of file, or any non standard text file, in PowerShell 2.0?

Your pattern is incorrect. The syntax of the options in .rdp files is
name:type:value
In your case:
promptcredentialonce:i:0
However, you're trying to match something with a space after the option name (which doesn't exist):
promptcredentialonce: (.*)
Without a match the .Matches property is empty and .Group[1] attempts an indexed access on a null value.
If you want the value including the type, remove the space:
promptcredentialonce:(.*)
If you want just the value, change the pattern to something like this:
promptcredentialonce:\w+:(.*)

Related

Is it possible to redirect output to a file using the redirection operator without writing a byte-order mark in Powershell?

Is there any way to omit the byte-order mark when redirecting the output stream to a file? For example, if I want to take the contents of an XML file and replace a string with a new value, I need to do create a new encoding and write the new output to a file like the following which is rather ham-handed:
$newContent = ( Get-Content .\settings.xml ) -replace 'expression', 'newvalue'
$UTF8NoBom = New-Object System.Text.UTF8Encoding( $false )
[System.IO.File]::WriteAllText( '.\settings.xml', $newContent, $UTF8NoBom )
I have also tried using Out-File, but specifying UTF8 as the encoding still contains a BOM:
( Get-Content .\settings.xml ) -replace 'expression', 'newvalue' | Out-File -Encoding 'UTF8' .\settings.xml
What I want to be able to do is simply redirect to a file without a BOM:
( Get-Content .\settings.xml ) -replace 'expression, 'newvalue' > settings.xml
The problem is that the BOM which is added to the output file routinely cause issues when reading these files from other applications (most notably, most applications which read an XML blow up if I modify the XML and it begins with a BOM, Chef Client also doesn't like a BOM in a JSON attributes file). Short of me writing a function like Write-FileWithoutBom to accept pipeline input and an output path, is there any way I can simply "turn off" writing a BOM when redirecting output to a file?
The solution doesn't necessarily have to use the redirection operator. If there is a built-in cmdlet I can use to output to a file without a BOM, that would be acceptable as well.
In Windows PowerShell as of v5.1 (the latest and last version), there is NO (direct) built-in way to get UTF-8 encoding without a BOM.
In v5.1+ you can change the default encoding for > / >> as follows, but if you choose utf8, you still get a BOM:
$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
To avoid a BOM, either direct use of .NET APIs or a workaround via New-Item is required - see this answer.
Unfortunately, it is unlikely that Windows PowerShell will ever support creation of BOM-less UTF-8 files.[1]
PowerShell Core (v6+), by contrast, uses BOM-less UTF-8 by default (both for Out-File / > and Set-Content) and offers you a choice of BOM or no-BOM via -Encoding specifiers utf8 and utf8BOM.
[1] From a Microsoft blog post, emphasis added: "Windows PowerShell 5.1, much like .NET Framework 4.x, will continue to be a built-in, supported component of Windows 10 and Windows Server 2016. However, it will likely not receive major feature updates or lower-priority bug fixes." and, in a comment, "The goal with PowerShell Core 6.0 and all the compatibility shims is to supplant the need for Windows PowerShell 6.0 while converging the ecosystem on PowerShell Core. So no, we currently don’t have any plans to do a Windows PowerShell 6.0."

Getting errors when trying to apply SQL files with PowerShell

When I manually apply a SQL file, like a re-indexing job, everything runs perfectly. I want to automate applying SQL files in powershell, but I'm getting all kinds of incorrect syntax errors when using Get-Content. Is there a better way to get a SQL files contents, then apply those contents on a remote server that doesn't re-format the code to the point where I get incorrect syntax errors.
Generic error I get (any syntax might throw an error - ps seems to be mis-applying the syntax when getting the content of the file):
Incorrect syntax near [anything]
Note: all GOs have been removed, so this isn't related to those; it may throw an error due to a begin, a goto, etc. The reason is that it's not retaining how the SQL file is built.
Update
The SQL files can be anything from adding permissions to creating an index to building a table to creating a stored procedure. I have about 100 SQL files. If I manually execute them, they all work, so this isn't related to bad SQL syntax, but related to how Powershell is reading the SQL syntax and running it as a command.
Answer
The below appears to work:
Get-Content $file -Raw
but I'm getting all kinds of incorrect syntax errors when using Get-Content
Get-Content will return an array of strings. What you need to be using is a single string. If you have at least PowerShell 3.0 then the -Raw switch is what you want.
Get-Content $file -Raw
Earlier versions you can use
Get-Content $file | Out-String
For exceptionally large files you can use .Net StreamReader's but I don't think that will be required here.
How are you "applying a SQL file"? If you're passing the contents of the file into Invoke-SQLCmd, you'll need to use -Raw like #Matt said.
However, you don't even really need to do that. Invoke-SQLCmd lets you pass a filename directly into it. Use the -Inputfile parameter.

Remove some characters from filename using powershell

I have a 100 files Which are named for instance: (Without quotes)
"Managing and Improving Own Learning [L3] {CBA849}" and
"Note-taking and Note-making [L3] {CBA851}"
I would like to rename it in a such way that it only shows "CBA849" and "CBA851" and remove anything else.
Another words I would like to keep file code inside {....} curly brackets.
Is there a way we can implement this? (Note: It's not replacing characters)
Thanks
Rename-Item -LiteralPath $path ([regex]::match($path, '{(.+)}')).Groups[1].Value
You need -LiteralPath because the filename contains brackets.
[regex]::match($path, '{(.+)}') matches the curly braces and their contents, and captures the contents into a match group. .Groups[1].Value returns the value of the first (and in this case, the only) match group.
This assumes that all the files are named in the format shown in the question. If it's possible that there might be curly braces elsewhere in the name, change the regex {(.+)} to {(.+?)}$.
I'd personally use a Regex match:
GCI $path | ?{$_.Name -match "(?:.*?{)(.*?)(?:})(\..*)?$"}|%{$_.MoveTo("$($_.Directory)\$($matches[1])$($matches[2])")}
Edit: As Adi Inbar says, I have created an overly complicated RegEx pattern. Simplified as he suggested (though still allowing for extensions) is a revised answer:
GCI $path | ?{$_.BaseName -match "{(.*?)}$"}|%{$_.MoveTo("$($_.Directory)\$($matches[1])$($_.Extension)")}
Edit: Ok, here's the breakdown...
GCI is short for Get-ChildItem, it pulls a listing of the directory specified, but I think you probably figured that one out.
Then it pipes to a Where{} clause(? is an alias for Where). It matches the BaseName of the files and folders provided by the GCI command. The BaseName property is actually one generated by PowerShell that takes the name of the file, extension and all, and then removes the extension (with preceding period) from it so if the file name is Sample.txt then it provides you with Sample as the BaseName.
It matches that against a RegEx (short for Regular Expression) pattern. If you don't know what RegEx is, please feel free to look it up and read up on it (Google is your friend). The basics is that it matches a pattern instead of actual text. In this case the pattern is anything at the end of the file name that is between curly braces.
Past that it enters a ForEach loop (I used the % alias for ForEach). For each file that matched the RegEx pattern it performs the MoveTo() method for that file. The location that it is moving it to is that file's current directory (gotten with $.Directory), followed by a backslash, followed by $Matches[1] (I'll get to that in a second), and then the original extension of the file (gotten with $.Extension). Now you'll see I wrapped the Directory and Extension in a sub-expression $() because with string extrapolation (how it auto-magically expands variables if you put them within double quotes) if you try to specify a property of a variable you have to put it in a sub-expression. Otherwise it tries to expand just the variable itself, and shows the .Whatever property name in plain text.
Lastly, $Matches is an automatic variable that is populated when you make a match with a few things (such as <something> -match <something else> like we did in the Where clause). The first record of it is the whole string that was matched <something>, and then the next records are the matches based on <something else>.
I hope that clears it all up for you. If you have specific questions let me know. If this answer resolved your question please mark it as accepted.
$f=gi $filepath;
$f.MoveTo($f.fullname.Replace($f.name,$f.name.substring($f.name.indexof("{")+1,($f.name.indexof("}")-1)-$f.name.indexof("{"))+$f.extension))
Get the File you're looking to rename as a [System.IO.FileInfo] object using get-item (gi).
Once you have the file object in $f the script is doing:
MoveTo
$f.FullName: The full path of the existing file (C:\some\dir\Test {ABC123}.txt)
Modify FullName to be the new filename by using the Replace function to replace the old filename ($f.name), with the desired name
The Substring function of the filename will allow you to get just the string between the curly braces.
Find the index of the OpenCurlyBracket within the name string
Find the index of the CloseCurlyBracket within the name string
Once the text between the curly brackets is identified with the Substring function, append the file extension to the new filename

How to remove specific characters from a file name?

I have bunch of files that need to have a (.) dot removed from the file-name. Eg. "Mr.-John-Smith.jpg" to "Mr-John-Smith.jpg". I don't have real experience with programming and know only html/css and a little javascript. I found another identical question here on stackoverflow, but what I gathered it was fixed on linux system and BASH was used.
Anyways, if anyone could provide me a tutorial on which program to use for this and what code to execute in that program to make it happen I'd be grateful.
if you are using a windows environment (which i guess you do)
you can download this free utility to mass change file names !
main page :
http://www.bulkrenameutility.co.uk/Main_Intro.php
download page :
http://www.bulkrenameutility.co.uk/Download.php
its easy to use
enjoy
If your file names in a file...
1- Open Microsoft Word or any text editor. Press ctrl+h and then search "." without quotes then replace it with blank character.
2- It will remove all dots, again bring "." to your file extention such as .jpg , .png searh your file extention for example "jpg" and replace it with ".jpg"
It will works %100, i am using this method everytime.
if they are not in a file and if you want do somethings in your operation systems' file system
Try this program. It is very useful for this operation;
Download
To remove all except the extension dot from all files in a directory, you can use PowerShell that comes with newer versions of Windows, and can be downloaded for older versions;
Line breaks inserted for readability, this should go on one line;
PS> dir | rename-item -newname {
[System.IO.Path]::GetFileNameWithoutExtension($_.name).Replace(".","") +
[System.IO.Path]::GetExtension($_.name); }
What it does is to take the file name without an extension and remove all dots in it, and then add back the extension. It then renames the file to the resulting name.
This will change for example do.it.now to doit.now, or in your case, Mr.-John-Smith.jpg to Mr-John-Smith.jpg.

Check in to ClearCase fails

I am trying to add a file into ClearCase, but I am getting the following error:
Error adding 'C:\PATH\file.dbc' to source control.
Changed Protection on "C:\PATH\file.dbc".
Created branch "C:\PATH\file.dbc" version "\main\0".
Type manager "text_file_delta" failed create_version operation.
Checked the following:
There are lines that have over 8000 characters and they must stay that way, so it can not use the "text_file_delta" as the type manager. I changed the type of one file to "compressed_file" and I was able to check it in.
I tried to add dbc compressed_file -name "*.[dD][bB][cC]" ; to the default.magic file. Then, I tried to check it with ct file test.dbc and it said that it is a compressed_file, but when I try to add an actual .dbc file to source control, it still gives me the error about the "text_file_delta" failing.
Is there something that I am missing with this? Maybe I put the line in the wrong part of the default.magic file?
Note: the only default.magic file that I am able to find is on the server side, is this correct? (I would rather it check here instead of everyone having to make one on their client.)
Make sure the default.magic file is taken into account, and is in the right directory, as mentioned in "About the ClearCase Magic file".
Make sure you did add the new rule in the right place in that magic file: see "How file types are determined when creating a new element"
Note: This is the first section in the default.magic file.
Example:
# Match by name without examining data
core file : -name "core" ;
compressed_file : -name "*.[nN][eE][wW]";
Note: The new file-typing rule that you add must come before the following line in the magic file:
text_file : -printable ;
compressed_file : !-printable ;
Use a personal magic file rather than modifying the default one:
Caution: It is highly recommended that you not modify the default.magic file directly as the next time an upgrade is performed, a new default.magic file will be created and your changes will be lost.
Creating a personal magic file with a name that is alphabetically before the "d" in the default.magic file name (such as cc.magic) will allow ClearCase to parse this file before the default.
It is better to create a personal magic file and possibly setting the MAGIC_PATH variable instead.

Resources