programing

BOM을 사용하지 않고 PowerShell을 사용하여 UTF-8에 파일 쓰기

powerit 2023. 4. 8. 09:53
반응형

BOM을 사용하지 않고 PowerShell을 사용하여 UTF-8에 파일 쓰기

Out-File UTF-8을 할 때 로 사용하는 것 .

$MyFile = Get-Content $MyPath
$MyFile | Out-File -Encoding "UTF8" $MyPath

PowerShell을 사용하여 BOM이 없는 UTF-8에 파일을 쓰는 방법은 무엇입니까?

업데이트 2021

PowerShell은 10년 전에 이 질문을 쓴 이후로 조금 바뀌었습니다.아래 여러 개의 답변을 확인하세요. 좋은 정보가 많이 있습니다!

.NET 클래스 사용 및 패스$False효과가 있는 것 같습니다.

$MyRawString = Get-Content -Raw $MyPath
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
[System.IO.File]::WriteAllLines($MyPath, $MyRawString, $Utf8NoBomEncoding)

현시점에서는 @M에 대한 코멘트에서 @Roman Kuzmin이 추천하는 솔루션을 사용하는 이 적절합니다.Dudley 답변:

[IO.File]::WriteAllLines($filename, $content)

불필요한 System네임스페이스 클리어 - 기본적으로는 자동으로 대체됩니다.)

이게 UTF가 아닌 줄 알았는데, 효과가 있는 것 같은 아주 간단한 해결책을 찾았어요...

Get-Content path/to/file.ext | out-file -encoding ASCII targetFile.ext

이것은 소스 포맷에 관계없이 bom 파일이 없는 utf-8이 됩니다.

참고: 이 답변Windows PowerShell에 적용됩니다.반대로 크로스 플랫폼 PowerShell Core 에디션(v6+)에서는 BOM을 사용하지 않는 UTF-8이 모든 cmdlet에서 기본 인코딩입니다.

  • 즉, 다음과 같습니다.PowerShell [Core] 버전 6 이상을 사용하는 경우 기본적으로 BOM-less UTF-8 파일제공됩니다(이 파일은 다음을 사용하여 명시적으로 요청할 수도 있음).-Encoding utf8-Encoding utf8NoBOM단, BOM을 사용한 부호화는-utf8BOM를 참조해 주세요.

  • Windows 10 이상을 실행하고 있으며 시스템 전체에 걸쳐 BOM 미사용 UTF-8 인코딩으로 전환하고 싶다면 Windows PowerShell에서도 BOM 미사용 UTF-8을 일관되게 사용할 수 있습니다.이 답변은 다음과 같습니다.


M을 보완하기 위해. Dudley의 심플하고 실용적인 답변(ForNeVeR의 보다 간결한 개혁):

  • 간단한 (비스트리밍) PowerShell 네이티브 대안은 Windows PowerShell에서도 기본적으로 BOM-less UTF-8 파일을 생성하는 것입니다.

    # Note the use of -Raw to read the file as a whole.
    # Unlike with Set-Content / Out-File *no* trailing newline is appended.
    $null = New-Item -Force $MyPath -Value (Get-Content -Raw $MyPath)
    
    • 을 「」와 같은 하려면 , 「」를 사용합니다.Out-File파이프가 1번으로 연결된다. 예:

       $null = New-Item -Force Out.txt -Value (Get-ChildItem | Out-String) 
      
  • 편의상 다음과 같은 파이프라인 기반의 대체 수단인 고급 커스텀 기능을 다음에 나타냅니다.

    • 하면 ' 때처럼.Out-File파이프라인에서
    • 됩니다.Out-File.
    • 추 an-UseLF의 LF 전용 스위치)을 사용할 수 ."`n"의 CRLF Windows CRLF 줄바꿈)이"`r`n" )는 보통 받습니다 ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ.

예:

(Get-Content $MyPath) | Out-FileUtf8NoBom $MyPath # Add -UseLF for Unix newlines

note에 주의해 주세요.(Get-Content $MyPath) 둘러싸여 있습니다.(...)파이프라인을 통해 결과를 전송하기 전에 파일 전체를 열고, 완전히 읽고, 닫습니다.이것은, 같은 파일에 다시 쓸 수 있도록 하기 위해서 필요합니다(갱신할 필요가 있습니다).
일반적으로 이 은 ( 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」(a) 「 」의 2가지.

메모리 사용에 관한 주의사항:

  • M. Dudley 자신의 대답과New-Item의 대안으로 파일 내용 전체를 먼저 메모리에 구축해야 합니다.이것은 큰 입력 세트에 문제가 있을 수 있습니다.
  • 다음 함수는 프록시(래퍼) 함수로 구현되기 때문에 이 함수는 필요하지 않습니다(이 함수의 정의 방법에 대한 간결한 요약은 이 답변을 참조하십시오).

함수의 소스 코드:

주의: 이 기능은 MIT 라이선스Gist로도 사용할 수 있으며, 으로도 Gist만 유지됩니다.

다음의 커맨드를 사용해 직접 인스톨 할 수 있습니다(개인적으로는, 인스톨 하는 것이 안전하다고 확신하고 있습니다만, 이 방법으로 스크립트를 직접 실행하기 전에, 반드시 스크립트의 내용을 확인해 주세요).

# Download and define the function.
irm https://gist.github.com/mklement0/8689b9b5123a9ba11df7214f82a673be/raw/Out-FileUtf8NoBom.ps1 | iex
function Out-FileUtf8NoBom {

  <#
  .SYNOPSIS
    Outputs to a UTF-8-encoded file *without a BOM* (byte-order mark).

  .DESCRIPTION

    Mimics the most important aspects of Out-File:
      * Input objects are sent to Out-String first.
      * -Append allows you to append to an existing file, -NoClobber prevents
        overwriting of an existing file.
      * -Width allows you to specify the line width for the text representations
        of input objects that aren't strings.
    However, it is not a complete implementation of all Out-File parameters:
      * Only a literal output path is supported, and only as a parameter.
      * -Force is not supported.
      * Conversely, an extra -UseLF switch is supported for using LF-only newlines.

  .NOTES
    The raison d'être for this advanced function is that Windows PowerShell
    lacks the ability to write UTF-8 files without a BOM: using -Encoding UTF8 
    invariably prepends a BOM.

    Copyright (c) 2017, 2022 Michael Klement <mklement0@gmail.com> (http://same2u.net), 
    released under the [MIT license](https://spdx.org/licenses/MIT#licenseText).

  #>

  [CmdletBinding(PositionalBinding=$false)]
  param(
    [Parameter(Mandatory, Position = 0)] [string] $LiteralPath,
    [switch] $Append,
    [switch] $NoClobber,
    [AllowNull()] [int] $Width,
    [switch] $UseLF,
    [Parameter(ValueFromPipeline)] $InputObject
  )

  begin {

    # Convert the input path to a full one, since .NET's working dir. usually
    # differs from PowerShell's.
    $dir = Split-Path -LiteralPath $LiteralPath
    if ($dir) { $dir = Convert-Path -ErrorAction Stop -LiteralPath $dir } else { $dir = $pwd.ProviderPath }
    $LiteralPath = [IO.Path]::Combine($dir, [IO.Path]::GetFileName($LiteralPath))
    
    # If -NoClobber was specified, throw an exception if the target file already
    # exists.
    if ($NoClobber -and (Test-Path $LiteralPath)) {
      Throw [IO.IOException] "The file '$LiteralPath' already exists."
    }
    
    # Create a StreamWriter object.
    # Note that we take advantage of the fact that the StreamWriter class by default:
    # - uses UTF-8 encoding
    # - without a BOM.
    $sw = New-Object System.IO.StreamWriter $LiteralPath, $Append
    
    $htOutStringArgs = @{}
    if ($Width) { $htOutStringArgs += @{ Width = $Width } }

    try { 
      # Create the script block with the command to use in the steppable pipeline.
      $scriptCmd = { 
        & Microsoft.PowerShell.Utility\Out-String -Stream @htOutStringArgs | 
          . { process { if ($UseLF) { $sw.Write(($_ + "`n")) } else { $sw.WriteLine($_) } } }
      }  
      
      $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
      $steppablePipeline.Begin($PSCmdlet)
    }
    catch { throw }

  }

  process
  {
    $steppablePipeline.Process($_)
  }

  end {
    $steppablePipeline.End()
    $sw.Dispose()
  }

}

버전 6 이상에서는 다음 기능이 지원됩니다.UTF8NoBOMset-contentout-file의 양쪽 모두에 대해 부호화를 실시합니다.또, 이것을 디폴트 부호화로서도 사용합니다.

따라서 위의 예에서는 다음과 같습니다.

$MyFile | Out-File -Encoding UTF8NoBOM $MyPath

「」를 사용하고 Set-ContentOut-File, 、 「 」 、 「 」라고를 지정할 수 있습니다.Byte바이트 배열을 파일에 쓰는 데 사용할 수 있습니다.BOM을 송신하지 않는 커스텀 UTF8 인코딩과 조합하면, 다음의 결과가 됩니다.

# This variable can be reused
$utf8 = New-Object System.Text.UTF8Encoding $false

$MyFile = Get-Content $MyPath -Raw
Set-Content -Value $utf8.GetBytes($MyFile) -Encoding Byte -Path $MyPath

「」를 사용하는 [IO.File]::WriteAllLines()또는 실제 파일 경로뿐만 아니라 모든 유형의 항목 및 경로에서 정상적으로 작동합니다.

이 스크립트는 BOM이 없는 UTF-8로 변환하여 DIRECTOR1 내의 모든 .txt 파일을 DIRECTOR2로 출력합니다.

foreach ($i in ls -name DIRECTORY1\*.txt)
{
    $file_content = Get-Content "DIRECTORY1\$i";
    [System.IO.File]::WriteAllLines("DIRECTORY2\$i", $file_content);
}

이것은, , 스페이스나 줄바꿈가 없는 경우에만 유효합니다.
를 들어 파일, 또는 수 있는 파일인 (SQL 파일, Java 파일 등)

ASCII(UTF8 하고, ( 치환)할 수 ( 「 」 ( UTF8 ) 。$strgc $src다음 중 하나:

" "    |  out-file  -encoding ASCII  -noNewline  $dest
$str  |  out-file  -encoding UTF8   -append     $dest

원라이너로서

$dest ★★★★★★★★★★★★★★★★★」$str사용 사례에 따라 다음을 수행합니다.

$_ofdst = $dest ; " " | out-file -encoding ASCII -noNewline $_ofdst ; $src | out-file -encoding UTF8 -append $_ofdst

단순한 기능으로서

function Out-File-UTF8-noBOM { param( $str, $dest )
  " "    |  out-file  -encoding ASCII  -noNewline  $dest
  $str  |  out-file  -encoding UTF8   -append     $dest
}

소스 파일과 함께 사용:

Out-File-UTF8-noBOM  (gc $src),  $dest

문자열과 함께 사용:

Out-File-UTF8-noBOM  $str,  $dest
  • " "로 를 계속합니다: " "Out-File:

    "more foo bar"  |  Out-File -encoding UTF8 -append  $dest
    

오래된 질문, 새로운 답변:

"구" powershell은 BOM을 쓰지만 새로운 플랫폼에 의존하지 않는 변형은 다르게 동작합니다.디폴트는 「No BOM」으로, 스위치를 개입시켜 설정할 수 있습니다.

- 부호화

대상 파일의 인코딩 유형을 지정합니다.기본값은 utf8NoBOM 입니다.

이 파라미터에 사용할 수 있는 값은 다음과 같습니다.

  • ascii : ASCII(7비트) 문자 세트의 부호화를 사용합니다.
  • bigendian unicode:빅 엔디안 바이트 순서를 사용하여 UTF-16 형식으로 인코딩합니다.
  • oem: MS-DOS 및 콘솔 프로그램에 기본 인코딩을 사용합니다.
  • 유니코드:little-endian 바이트 순서를 사용하여 UTF-16 형식으로 인코딩합니다.
  • utf7: UTF-7 형식으로 인코딩합니다.
  • utf8: UTF-8 형식으로 인코딩합니다.
  • utf8BOM: 바이트 순서 마크(BOM)를 사용하여 UTF-8 형식으로 인코딩합니다.
  • utf8 NoBOM: 바이트 순서 마크(BOM) 없이 UTF-8 형식으로 인코딩
  • utf32: UTF-32 형식으로 인코딩합니다.

출처 : https://learn.microsoft.com/de-de/powershell/module/Microsoft.PowerShell.Utility/Out-File?view=powershell-7 강조 내 것

PowerShell 5.1의 경우 다음 설정을 사용합니다.

제어판, 지역, 관리, 시스템 로케일 변경, Unicode UTF-8 사용으로 전 세계 언어 지원

다음으로 PowerShell에 다음과 같이 입력합니다.

$PSDefaultParameterValues['*:Encoding'] = 'Default'

또는 PowerShell 6 이상으로 업그레이드할 수 있습니다.

https://github.com/PowerShell/PowerShell

Set-Content 명령어만 사용할 수 있습니다.다른 것은 필요 없습니다.

시스템의 powershell 버전은 다음과 같습니다.

PS C:\Users\XXXXX> $PSVersionTable.PSVersion | fl


Major         : 5
Minor         : 1
Build         : 19041
Revision      : 1682
MajorRevision : 0
MinorRevision : 1682

PS C:\Users\XXXXX>

따라서 다음과 같은 것이 필요합니다.

PS C:\Users\XXXXX> Get-Content .\Downloads\finddate.txt
Thursday, June 23, 2022 5:57:59 PM
PS C:\Users\XXXXX> Get-Content .\Downloads\finddate.txt | Set-Content .\Downloads\anotherfile.txt
PS C:\Users\XXXXX> Get-Content .\Downloads\anotherfile.txt
Thursday, June 23, 2022 5:57:59 PM
PS C:\Users\XXXXX>

이제 스크린샷에 따라 파일을 확인해보니 utf8. another file 입니다.txt

BOM을 사용하지 않고 여러 파일을 UTF-8로 확장자로 변경합니다.

$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
foreach($i in ls -recurse -filter "*.java") {
    $MyFile = Get-Content $i.fullname 
    [System.IO.File]::WriteAllLines($i.fullname, $MyFile, $Utf8NoBomEncoding)
}
    [System.IO.FileInfo] $file = Get-Item -Path $FilePath 
    $sequenceBOM = New-Object System.Byte[] 3 
    $reader = $file.OpenRead() 
    $bytesRead = $reader.Read($sequenceBOM, 0, 3) 
    $reader.Dispose() 
    #A UTF-8+BOM string will start with the three following bytes. Hex: 0xEF0xBB0xBF, Decimal: 239 187 191 
    if ($bytesRead -eq 3 -and $sequenceBOM[0] -eq 239 -and $sequenceBOM[1] -eq 187 -and $sequenceBOM[2] -eq 191) 
    { 
        $utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False) 
        [System.IO.File]::WriteAllLines($FilePath, (Get-Content $FilePath), $utf8NoBomEncoding) 
        Write-Host "Remove UTF-8 BOM successfully" 
    } 
    Else 
    { 
        Write-Warning "Not UTF-8 BOM file" 
    }  

소스 PowerShell을 사용하여 파일에서 UTF8 바이트 순서 표시(BOM)를 삭제하는 방법

「 」를 사용하고 [System.IO.File]::WriteAllLines() 두 번째 는 '두 번째 파라미터'를 '어울리다'로 String[]이 ()의 )$MyFileObject[] path'로 $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath)를 들면 다음과 같습니다.

$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
Get-ChildItem | ConvertTo-Csv | Set-Variable MyFile
[System.IO.File]::WriteAllLines($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath), [String[]]$MyFile, $Utf8NoBomEncoding)

「 」를 사용하고 [System.IO.File]::WriteAllText()에 접속할 가 있는 경우가 | Out-String |CRLF를 CRLF와 함께 ).ConvertTo-Csv

$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
Get-ChildItem | ConvertTo-Csv | Out-String | Set-Variable tmp
[System.IO.File]::WriteAllText("/absolute/path/to/foobar.csv", $tmp, $Utf8NoBomEncoding)

ㄴㄴㄴ데 하다'를 해도 됩니다.[Text.Encoding]::UTF8.GetBytes()Set-Content -Encoding Byte:

$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
Get-ChildItem | ConvertTo-Csv | Out-String | % { [Text.Encoding]::UTF8.GetBytes($_) } | Set-Content -Encoding Byte -Path "/absolute/path/to/foobar.csv"

참조: ConvertTo-Csv 결과를 BOM을 사용하지 않고 UTF-8 파일에 쓰는 방법

PowerShell에서도 동일한 오류가 발생하여 이 분리를 사용하여 수정했습니다.

$PSDefaultParameterValues['*:Encoding'] = 'utf8'

사용하고 있는 기술 중 하나는 Out-File cmdlet을 사용하여 출력을 ASCII 파일로 리다이렉트하는 것입니다.

예를 들어 Oracle에서 실행할 다른 SQL 스크립트를 생성하는 SQL 스크립트를 실행하는 경우가 많습니다.단순 리다이렉션(">)에서는 출력은 UTF-16으로 SQLPlus에서 인식되지 않습니다.이 문제를 해결하려면:

sqlplus -s / as sysdba "@create_sql_script.sql" |
Out-File -FilePath new_script.sql -Encoding ASCII -Force

생성된 스크립트는 Unicode에 대한 우려 없이 다른 SQLPlus 세션을 통해 실행할 수 있습니다.

sqlplus / as sysdba "@new_script.sql" |
tee new_script.log

업데이트: 다른 사용자가 지적한 바와 같이 ASC 이외의 기능은 폐기됩니다.II 문자유저가 변환을 「강제」하는 방법을 요구했기 때문에, 데이터에 그러한 데이터가 포함되어 있지 않을지도 모르기 때문에, 그것을 신경쓰지 않는다고 생각합니다.

비 ASC 보존에 관심이 있는 경우II캐릭터 여러분, 정답이 아닙니다.

이 방법을 사용하여 UTF8-NoBOM 파일을 편집하고 올바른 인코딩으로 파일을 생성했습니다.

$fileD = "file.xml"
(Get-Content $fileD) | ForEach-Object { $_ -replace 'replace text',"new text" } | out-file "file.xml" -encoding ASCII

처음에는 이 방법에 대해 회의적이었지만, 깜짝 놀라서 효과가 있었습니다!

Powershell 버전 5.1에서 테스트 완료

BOM을 사용하지 않고 UTF8을 취득하기 위해 다음을 사용할 수 있습니다.

$MyFile | Out-File -Encoding ASCII

이 방법은 다음과 같습니다('UTF8' 대신 'Default' 사용).

$MyFile = Get-Content $MyPath
$MyFile | Out-File -Encoding "Default" $MyPath

결과는 BOM이 없는 ASCII입니다.

언급URL : https://stackoverflow.com/questions/5596982/using-powershell-to-write-a-file-in-utf-8-without-the-bom

반응형