Syntax error in powershell command in windows - powershell

I try to run two commands in a bat file using the powershell. My goal is to transform a file to a utf8 format. How can I achieve that?
Here is what I have so far:
PowerShell -Command (Get-Content 'ZipCode.csv' | Out-File 'ZipCode1.csv' -Encoding utf8)
I get the following error: "out-file is not recognized as an internal or external command"

The doublequotes seem sufficient to escape the pipe. Single quotes on the outside wouldn't work.
PowerShell "Get-Content ZipCode.csv | Out-File ZipCode1.csv -Encoding utf8"

If you're only using Out-File because your version of PowerShell doesn't include the -Encoding option with Set-Content, then it should read:
#"%__AppDir__%WindowsPowerShell\v1.0\powershell.exe" -NoProfile -Command "Get-Content -Path '.\ZipCode.csv' | Out-File -FilePath '.\ZipCode1.csv' -Encoding UTF8"
Obviously if you have a Version of PowerShell where Set-Content has the required -Encoding option, use it instead:
#"%__AppDir__%WindowsPowerShell\v1.0\powershell.exe" -NoProfile -Command "Get-Content -LiteralPath 'ZipCode.csv' | Set-Content -LiteralPath 'ZipCode1.csv' -Encoding UTF8"
These could obviously be shortened to remove the robustness and use aliases/shorthand:
#PowerShell -NoP "GC '.\ZipCode.csv'|Out-File '.\ZipCode1.csv' -E UTF8"
#PowerShell -NoP "GC -LP 'ZipCode.csv'|SC -LP 'ZipCode1.csv' -En UTF8"
I prefer to use -LiteralPath because I have a tendency to use [] in my file naming, and those can be problematic in filenames. Change the output file name to ZipCode[1], then try the -Set-Content version code with -Path or nothing instead of -LiteralPath/-LP option, and you should see what I mean.

Related

Powershell Get-Content failing spuriously

I have a fairly simple PS script that was working perfectly, and now has suddenly started giving errors. I have narrowed the problem portion to a couple of Get-Content statements. Here's what the affected part of the script looks like:
$pathSource = "D:\FileDirectory"
Set-Location -Path $pathSource
Get-Content -Encoding UTF8 -Path FilesA*.txt | Out-File -Encoding ASCII FilesA_Digest.txt
Get-Content -Encoding UTF8 -Path FilesB*.txt | Out-File -Encoding ASCII FilesB_Digest.txt
This part of the script gathers up a collection of like-named files and concatenates them into a single text file for uploading to an FTP site. The Get-Content/Out-File was needed as the original files are encoded incorrectly for the FTP site. The script was working perfectly, running once each night for several weeks. Now, it gets the following error when the Get-Content statements are reached:
Get-Content : A parameter cannot be found that matches parameter name 'Encoding'.
At D:\FileDirectory\Script.ps1
Environment is Windows Server 2016. I've tried different variations on the Get-Content parameters, but nothing has worked. I know there is a bug that affects network-mapped drives, but that's not the case here -- all files are local.
Any ideas/suggestions?
The only plausible explanation I can think of is that a custom Get-Content command that lacks an -Encoding parameter is shadowing (overriding) the standard Get-Content cmdlet in the PowerShell session that's executing your script.
To demonstrate:
# Define a custom Get-Content command (function) that accepts only
# a (positional) -Path parameter, not also -Encoding.
function Get-Content { [CmdletBinding()] param([string] $Path) }
# Now try to use Get-Content -Encoding
Get-Content -Encoding Utf8 FilesA*.txt
You'll see the same error message as in your question.
Use Get-Command Get-Content -All to see all commands named Get-Content, with the effective command listed first.
Then examine where any custom commands may come from; e.g., your $PROFILE script may contain one.
To rule out $PROFILE as the culprit, start PowerShell without loading the profile script and examine Get-Content then:
powershell -noprofile # Windows PowerShell
pwsh -noprofile # PowerShell Core
A simple way to rule out custom overrides ad hoc is to call a command by its module-qualified name:
Microsoft.Powershell.Management\Get-Content ...
You can determine a built-in cmdlet's module name of origin as follows:
PS> (Get-Command Get-Content -All)[-1].ModuleName
Microsoft.PowerShell.Management
In a pinch you can also infer the originating module name from the URL of the help topic:
Googling Get-Content will take you to https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-content - note how the cmdlet's module name, microsoft.powershell.management (case doesn't matter), is the penultimate (next to last) URI component.
It seems an issue with the out command. Can you please try below code :
$pathSource = "D:\FileDirectory"
Set-Location -Path $pathSource
Get-Content -Encoding UTF8 -Path FilesA*.txt | Set-Content -Encoding ASCII -path FilesA_Digest.txt
Get-Content -Encoding UTF8 -Path FilesB*.txt | Set-Content -Encoding ASCII -path FilesB_Digest.txt
Well, I don't know why it failed, but I can say that I have completely re-written the script and now it works. I have to note that, given the errors that were occurring, I also don't know why it is now working.
I am using the exact same calls to the Get-Content commandlet, with the -Encoding parameter and the pipe to Out-File with its own -Encoding parameter. I am doing the exact same actions as the previous version of the script. The only part that is significantly different is the portion that performs the FTP transfer of the processed files. I'm now using only PowerShell to perform the transfer rather than CuteFTP and it all seems to be working correctly.
Thanks to everyone who contributed.
Cheers
Norm
Not sure if it helps, but I was running into the same with:
$n = ni '[hi]' -value 'some text'
gc $n -Encoding Byte
$f = ls *hi*
$f.where{$_.name -eq '[hi]'}.Delete()
also looks like there's already a chain of SOs about this known bug see this answer

tee with utf-8 encoding

I'm trying to tee a server's output to both the console and a file in Powershell 4. The file is ending up with a UTF-16 encoding, which is incompatible with some other tools I'm using. According to help tee -full:
Tee-Object uses Unicode enocding when it writes to files.
...
To specify the encoding, use the Out-File cmdlet
So tee doesn't support changing encoding, and the help for both tee and Out-File don't show any examples of splitting a stream and encoding it with UTF-8.
Is there a simple way in Powershell 4 to tee (or otherwise split a stream) to a file with UTF-8 encoding?
One option is to use Add-Content or Set-Content instead of Out-File.
The *-Content cmdlets use ASCII encoding by default, and have a -Passthru switch so you can write to the file, and then have the input pass through to the console:
Get-Childitem -Name | Set-Content file.txt -Passthru
You would have to use -Variable and then write it out to a file in a separate step.
$data = $null
Get-Process | Tee-Object -Variable data
$data | Out-File -Path $path -Encoding Utf8
At first glance it seems like it's easier to avoid tee altogether and just capture the output in a variable, then write it to the screen and to a file.
But because of the way the pipeline works, this method allows for a long running pipeline to display data on screen as it goes along. Unfortunately the same cannot be said for the file, which won't be written until afterwards.
Doing Both
An alternative is to roll your own tee so to speak:
[String]::Empty | Out-File -Path $path # initialize the file since we're appending later
Get-Process | ForEach-Object {
$_ | Out-File $path -Append -Encoding Utf
$_
}
That will write to the file and back to the pipeline, and it will happen as it goes along. It's probably quite slow though.
Tee-object seems to invoke out-file, so this will make tee output utf8:
$PSDefaultParameterValues = #{'Out-File:Encoding' = 'utf8'}
First create the file using appropriate flags then append to it:
Set-Content out $null -Encoding Unicode
...
cmd1 | tee out -Append
...
cmdn | tee out -Append

Powershell logging from Invoke-Expression with encoding

I have an specific scenario where I have to log a batch file using Invoke-Expression in Powershell but my logs are being saved with "UCS-2 Little Endian" Encoding and I would like to save it with UTF-8 or any other encoding.
This is a simple example of what I'm trying to do:
batch file (test.bat):
echo Test
Powershell file (test.ps1):
Invoke-Expression "c:\test.bat > log.txt"
Is there a way I could change the encoding on log.txt?
You can try this:
C:\test.bat | Out-File C:\log.txt -Encoding UTF8
Or if for whatever reason you really have to use Invoke-Expression:
Invoke-Expression "C:\test.bat" | Out-File C:\log.txt -Encoding UTF8
Note that this will overwrite log.txt everytime. If you want to append to the file do this:
Invoke-Expression "C:\test.bat" | Out-File C:\log.txt -Encoding UTF8 -append
or
Invoke-Expression "C:\test.bat" | Add-Content C:\log.txt -Encoding UTF8

Encode file with cmd

I have a bat file that performs some actions and I need to encode a text file with UTF-8 format.
Is there any way to perform this in windows command line??
Thanks in advance.
Only with other programs which may or may not be installed. If you're targetting Windows 7 and higher you could just use PowerShell:
powershell -Command "&{ param($Path); (Get-Content $Path) | Out-File $Path -Encoding UTF8 }" somefile.txt

UTF8 encoding without BOM - PowerShell

I have a bat file where I encode some CSV files. The problem is that there are one character at the begining of the file once the encoding have been done (BOM byte I guess). This character bothers me cause after encoding, I use this file to generate a database.
Here is the line for encoding (inside bat file):
powershell -Command "&{ param($Path); (Get-Content $Path) | Out-File $Path -Encoding UTF8 }" CSVs\\pass.csv
Is there any way to encode the file without BOM (if this is the problem)??
Thanks!
I found the solution.
Just change the line with this:
powershell -Command "&{ param($Path); $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False); $MyFile = Get-Content $Path; [System.IO.File]::WriteAllLines($Path, $MyFile, $Utf8NoBomEncoding) }" CSVs\\pass.csv