NDLR: A en juger par les commentaires ultérieurs de l'OP, l'essentiel de cette question est: Comment pouvez-vous convertir un fichier avec des fins de ligne CRLF (style Windows) en LF uniquement ( Fichier de type Unix) dans PowerShell?
Voici mon script PowerShell:
$original_file ='C:\Users\abc\Desktop\File\abc.txt'
(Get-Content $original_file) | Foreach-Object {
$_ -replace "'", "2"`
-replace '2', '3'`
-replace '1', '7'`
-replace '9', ''`
-replace "`r`n",'`n'
} | Set-Content "C:\Users\abc\Desktop\File\abc.txt" -Force
Avec ce code, je peux remplacer 2 par 3, 1 par 7 et 9 par une chaîne vide. Je ne parviens pas à remplacer le saut de ligne retour chariot par le saut de ligne uniquement. Mais cela ne fonctionne pas.
Vous n'avez pas spécifié la version, je suppose que vous utilisez Powershell v3.
Essaye ça:
$path = "C:\Users\abc\Desktop\File\abc.txt"
(Get-Content $path -Raw).Replace("`r`n","`n") | Set-Content $path -Force
NDLR: Comme le souligne mike z dans les commentaires, Set-Content
Ajoute un CRLF de fin, ce qui n'est pas souhaité. Vérifiez avec: 'hi' > t.txt; (Get-Content -Raw t.txt).Replace("`r`n","`n") | Set-Content t.txt; (Get-Content -Raw t.txt).EndsWith("`r`n")
, ce qui donne $True
.
Notez que cela charge tout le fichier en mémoire, vous pouvez donc souhaiter une solution différente si vous souhaitez traiter des fichiers volumineux.
MISE À JOUR
Cela pourrait fonctionner pour la v2 (désolé nulle part pour tester):
$in = "C:\Users\abc\Desktop\File\abc.txt"
$out = "C:\Users\abc\Desktop\File\abc-out.txt"
(Get-Content $in) -join "`n" > $out
NDLR: Notez que cette solution (maintenant) écrit dans un fichier différent et n'est donc pas équivalente au (toujours imparfait) ) v3 solution. (Un fichier différent est ciblé pour éviter l'écueil qu'Ansgar Wiechers souligne dans les commentaires: en utilisant >
tronque le fichier cible avant l'exécution commence). Plus important encore, cependant: cette solution aussi ajoute un CRLF de fin, ce qui n'est pas souhaité. Vérifiez avec 'hi' > t.txt; (Get-Content t.txt) -join "`n" > t.NEW.txt; [io.file]::ReadAllText((Convert-Path t.NEW.txt)).endswith("`r`n")
, ce qui donne $True
.
Même réserve quant au chargement en mémoire.
Il s'agit d'une réponse à l'état de l'union à partir de Windows PowerShell v5.1/PowerShell Core v6.2.0 :
La réponse malheureuse d'Andrew Savinykh , bien qu'elle soit acceptée, est, au moment de la rédaction de cet article, fondamentalement défectueuse j'espère qu'il sera corrigé - il y a suffisamment d'informations dans les commentaires - et dans l'historique des modifications - pour le faire).
Réponse utile d'Ansgar Wiecher fonctionne bien , mais nécessite une utilisation directe du .NET Framework (et lit l'intégralité du fichier en mémoire, bien que cela puisse être modifié). L'utilisation directe du .NET Framework n'est pas un problème en soi, mais est plus difficile à maîtriser pour les novices et difficile à retenir en général.
Une version future de PowerShell Core aura unConvert-TextFile
applet de commande avec un -LineEnding
paramètre pour permettre la mise à jour sur place des fichiers texte avec un style de nouvelle ligne spécifique, comme en cours de discussion sur GitHub .
Dans PSv5 + , des solutions natives PowerShell sont désormais possibles , car Set-Content
prend désormais en charge -NoNewline
switch, qui empêche l'ajout indésirable d'un saut de ligne natif de la plate-forme[1] :
# Convert CRLFs to LFs only.
# Note:
# * (...) around Get-Content ensures that $file is read *in full*
# up front, so that it is possible to write back the transformed content
# to the same file.
# * + "`n" ensures that the file has a *trailing LF*, which Unix platforms
# expect.
((Get-Content $file) -join "`n") + "`n" | Set-Content -NoNewline $file
Ce qui précède repose sur Get-Content
la capacité de lire un fichier texte qui utilise toute combinaison de CR uniquement, CRLF et LF uniquement nouvelles lignes ligne par ligne.
Mises en garde :
Vous devez spécifier l'encodage de sortie à correspondre au fichier d'entrée dans l'ordre pour le recréer avec le même encodage. La commande ci-dessus ne spécifie PAS un codage de sortie; pour ce faire, utilisez -Encoding
; sans-Encoding
:
Le contenu du fichier d'entrée ainsi que sa copie transformée doivent tenir dans la mémoire dans son ensemble, ce qui peut être problématique avec gros fichiers d'entrée.
Il existe un risque de corruption de fichiers , si le processus de réécriture dans le fichier d'entrée est interrompu.
[1] En fait, s'il y a plusieurs chaînes à écrire, -NoNewline
ne place pas non plus de saut de ligne entre eux; dans le cas présent, cependant, cela n'est pas pertinent, car seule la chaîne un est écrite.
Solution alternative qui n'ajoutera pas un faux CR-LF:
$original_file ='C:\Users\abc\Desktop\File\abc.txt'
$text = [IO.File]::ReadAllText($original_file) -replace "`r`n", "`n"
[IO.File]::WriteAllText($original_file, $text)
Ajout d'une autre version basée sur l'exemple ci-dessus par @ ricky89 et @ mklement0 avec quelques améliorations:
Script à traiter:
LF-à-CRLF.ps1:
# get current dir
$currentDirectory = Split-Path $MyInvocation.MyCommand.Path -Parent
# create subdir CR-to-CRLF for new files
$outDir = $(Join-Path $currentDirectory "CR-to-CRLF")
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
# get all .txt files
Get-ChildItem $currentDirectory -Force | Where-Object {$_.extension -eq ".txt"} | ForEach-Object {
$file = New-Object System.IO.StreamReader -Arg $_.FullName
# Resulting file will be in CR-to-CRLF subdir
$outstream = [System.IO.StreamWriter] $(Join-Path $outDir $($_.BaseName + $_.Extension))
$count = 0
# read line by line, replace CR with CRLF in each by saving it with $outstream.WriteLine
while ($line = $file.ReadLine()) {
$count += 1
$outstream.WriteLine($line)
}
$file.close()
$outstream.close()
Write-Host ("$_`: " + $count + ' lines processed.')
}
Les éléments suivants pourront traiter rapidement de très gros fichiers.
$file = New-Object System.IO.StreamReader -Arg "file1.txt"
$outstream = [System.IO.StreamWriter] "file2.txt"
$count = 0
while ($line = $file.ReadLine()) {
$count += 1
$s = $line -replace "`n", "`r`n"
$outstream.WriteLine($s)
}
$file.close()
$outstream.close()
Write-Host ([string] $count + ' lines have been processed.')