{"id":1234,"date":"2026-09-11T10:47:03","date_gmt":"2026-09-11T10:47:03","guid":{"rendered":"https:\/\/techno.slomka.biz\/?p=1234"},"modified":"2026-09-11T10:47:03","modified_gmt":"2026-09-11T10:47:03","slug":"quick-crlf-to-lf-conversion-in-powershell-without-dos2unix","status":"publish","type":"post","link":"https:\/\/techno.slomka.biz\/?p=1234","title":{"rendered":"Quick CRLF-to-LF Conversion in PowerShell Without `dos2unix`"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Although this topic has been discussed so often, I think I can still contribute something regarding CRLF\/LF.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You write a shell script on Windows, copy it to a Linux server, run it \u2013 and get:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#EEFFFF;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#304047;color:#d5ffff\">Bash<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#EEFFFF;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>-bash: .\/deploy.sh: \/bin\/bash^M: bad interpreter: No such file or directory<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme\" style=\"background-color: #263238\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #FFCB6B\">-bash:<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">.\/deploy.sh:<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">\/bin\/bash^M:<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">bad<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">interpreter:<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">No<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">such<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">file<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">or<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">directory<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">(Newer bash versions are even less helpful: <code>cannot execute: required file not found<\/code>.)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The culprit is Windows line endings: <strong>**CRLF**<\/strong> (<code>\\r\\n<\/code>) instead of <strong>**LF**<\/strong> (<code>\\n<\/code>). Bash treats the trailing <code>\\r<\/code> as part of the command. If <code>dos2unix<\/code> is not at hand, PowerShell handles the conversion in a single line that isn&#8217;t particularly easy to remember:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#EEFFFF;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#304047;color:#d5ffff\">PowerShell<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#EEFFFF;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>&#91;IO.File&#93;::WriteAllText($p, (&#91;IO.File&#93;::ReadAllText($p) -replace \"`r`n\", \"`n\"))<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme\" style=\"background-color: #263238\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #89DDFF\">&#91;<\/span><span style=\"color: #C792EA\">IO.File<\/span><span style=\"color: #89DDFF\">&#93;<\/span><span style=\"color: #EEFFFF\">::WriteAllText<\/span><span style=\"color: #89DDFF\">($<\/span><span style=\"color: #EEFFFF\">p<\/span><span style=\"color: #89DDFF\">,<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">(&#91;<\/span><span style=\"color: #C792EA\">IO.File<\/span><span style=\"color: #89DDFF\">&#93;<\/span><span style=\"color: #EEFFFF\">::ReadAllText<\/span><span style=\"color: #89DDFF\">($<\/span><span style=\"color: #EEFFFF\">p<\/span><span style=\"color: #89DDFF\">)<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">-replace<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #EEFFFF\">`r`n<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #89DDFF\">,<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #EEFFFF\">`n<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #89DDFF\">))<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>## How it works<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8211; <code>[IO.File]::ReadAllText($p)<\/code> reads the whole file into a single string \u2013 line endings included.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8211; <code>-replace \"`r`n\", \"`n\"<\/code> replaces every CRLF with LF. Inside double quotes, <code>`r<\/code> and<code> `n<\/code> are PowerShell escape sequences for CR and LF.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8211; <code>[IO.File]::WriteAllText()<\/code> writes the string back as it is.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Why not simply <code>Get-Content<\/code> \/ <code>Set-Content<\/code>? Without <code>-Raw<\/code>, <code>Get-Content<\/code> splits the file into lines and drops the line endings, and <code>Set-Content<\/code> joins them again with the Windows default <code>\\r\\n<\/code> \u2013 exactly what you wanted to get rid of.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>## Three gotchas<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>**1. Use an absolute path.**<\/strong> .NET resolves relative paths against the process working directory, not against your current PowerShell location. After a <code>Set-Location<\/code>, <code>.\\deploy.sh<\/code> may point somewhere else \u2013 or nowhere. Resolve it first:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#EEFFFF;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#304047;color:#d5ffff\">PowerShell<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#EEFFFF;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>$p = Convert-Path .\\deploy.sh<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme\" style=\"background-color: #263238\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #89DDFF\">$<\/span><span style=\"color: #EEFFFF\">p <\/span><span style=\"color: #89DDFF\">=<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #82AAFF\">Convert-Path<\/span><span style=\"color: #EEFFFF\"> .\\deploy.sh<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>**2. Mind the encoding.**<\/strong> <code>ReadAllText()<\/code> assumes UTF-8 (unless a BOM says otherwise), <code>WriteAllText()<\/code> writes UTF-8 <strong>**without**<\/strong> BOM. For UTF-8 or plain ASCII scripts that is exactly what you want \u2013 a UTF-8 BOM is dropped on the way, which Linux tools appreciate anyway. <strong>**ANSI files (Windows-1252) with umlauts, however, get corrupted:**<\/strong> <code>\u00fc<\/code> turns into <code>\ufffd<\/code>. Pass the encoding explicitly in that case:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#EEFFFF;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#304047;color:#d5ffff\">PowerShell<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#EEFFFF;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>$enc = &#91;Text.Encoding&#93;::GetEncoding(1252)\n&#91;IO.File&#93;::WriteAllText($p, (&#91;IO.File&#93;::ReadAllText($p, $enc) -replace \"`r`n\", \"`n\"), $enc)<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme\" style=\"background-color: #263238\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #89DDFF\">$<\/span><span style=\"color: #EEFFFF\">enc <\/span><span style=\"color: #89DDFF\">=<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">&#91;<\/span><span style=\"color: #C792EA\">Text.Encoding<\/span><span style=\"color: #89DDFF\">&#93;<\/span><span style=\"color: #EEFFFF\">::GetEncoding<\/span><span style=\"color: #89DDFF\">(<\/span><span style=\"color: #F78C6C\">1252<\/span><span style=\"color: #89DDFF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #89DDFF\">&#91;<\/span><span style=\"color: #C792EA\">IO.File<\/span><span style=\"color: #89DDFF\">&#93;<\/span><span style=\"color: #EEFFFF\">::WriteAllText<\/span><span style=\"color: #89DDFF\">($<\/span><span style=\"color: #EEFFFF\">p<\/span><span style=\"color: #89DDFF\">,<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">(&#91;<\/span><span style=\"color: #C792EA\">IO.File<\/span><span style=\"color: #89DDFF\">&#93;<\/span><span style=\"color: #EEFFFF\">::ReadAllText<\/span><span style=\"color: #89DDFF\">($<\/span><span style=\"color: #EEFFFF\">p<\/span><span style=\"color: #89DDFF\">,<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">$<\/span><span style=\"color: #EEFFFF\">enc<\/span><span style=\"color: #89DDFF\">)<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">-replace<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #EEFFFF\">`r`n<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #89DDFF\">,<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #EEFFFF\">`n<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #89DDFF\">),<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">$<\/span><span style=\"color: #EEFFFF\">enc<\/span><span style=\"color: #89DDFF\">)<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>**3. The whole file goes into memory.**<\/strong> Fine for scripts and config files, not for multi-GB logs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>## Converting a whole directory<\/strong><\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#EEFFFF;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#304047;color:#d5ffff\">PowerShell<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#EEFFFF;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>Get-ChildItem -Filter *.sh -Recurse -File | ForEach-Object {\n    $t = &#91;IO.File&#93;::ReadAllText($_.FullName)\n    if ($t.Contains(\"`r`n\")) {\n        &#91;IO.File&#93;::WriteAllText($_.FullName, $t.Replace(\"`r`n\", \"`n\"))\n        \"converted: $($_.FullName)\"\n    }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme\" style=\"background-color: #263238\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #82AAFF\">Get-ChildItem<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">-<\/span><span style=\"color: #EEFFFF\">Filter <\/span><span style=\"color: #89DDFF\">*<\/span><span style=\"color: #EEFFFF\">.sh <\/span><span style=\"color: #89DDFF\">-<\/span><span style=\"color: #EEFFFF\">Recurse <\/span><span style=\"color: #89DDFF\">-<\/span><span style=\"color: #EEFFFF\">File <\/span><span style=\"color: #89DDFF\">|<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #82AAFF\">ForEach-Object<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #EEFFFF\">    <\/span><span style=\"color: #89DDFF\">$<\/span><span style=\"color: #EEFFFF\">t <\/span><span style=\"color: #89DDFF\">=<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">&#91;<\/span><span style=\"color: #C792EA\">IO.File<\/span><span style=\"color: #89DDFF\">&#93;<\/span><span style=\"color: #EEFFFF\">::ReadAllText<\/span><span style=\"color: #89DDFF\">($<\/span><span style=\"color: #EEFFFF\">_.FullName<\/span><span style=\"color: #89DDFF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #EEFFFF\">    <\/span><span style=\"color: #89DDFF; font-style: italic\">if<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">($<\/span><span style=\"color: #EEFFFF\">t.Contains<\/span><span style=\"color: #89DDFF\">(<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #EEFFFF\">`r`n<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #89DDFF\">))<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #EEFFFF\">        <\/span><span style=\"color: #89DDFF\">&#91;<\/span><span style=\"color: #C792EA\">IO.File<\/span><span style=\"color: #89DDFF\">&#93;<\/span><span style=\"color: #EEFFFF\">::WriteAllText<\/span><span style=\"color: #89DDFF\">($<\/span><span style=\"color: #EEFFFF\">_.FullName<\/span><span style=\"color: #89DDFF\">,<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">$<\/span><span style=\"color: #EEFFFF\">t.Replace<\/span><span style=\"color: #89DDFF\">(<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #EEFFFF\">`r`n<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #89DDFF\">,<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #EEFFFF\">`n<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #89DDFF\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #EEFFFF\">        <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #C3E88D\">converted: <\/span><span style=\"color: #89DDFF\">$($<\/span><span style=\"color: #EEFFFF\">_.FullName<\/span><span style=\"color: #89DDFF\">)<\/span><span style=\"color: #89DDFF\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #EEFFFF\">    <\/span><span style=\"color: #89DDFF\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #89DDFF\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><code>FullName<\/code> is always absolute (gotcha #1 solved), and files that are already clean are not touched. .<code>Replace()<\/code> is the plain string method \u2013 a literal replacement without the regex engine, same result.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>## Alternatives<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>**PowerShell cmdlets:**<\/strong><\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#EEFFFF;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#304047;color:#d5ffff\">PowerShell<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#EEFFFF;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>(Get-Content -Raw $p) -replace \"`r`n\", \"`n\" | Set-Content -NoNewline $p<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme\" style=\"background-color: #263238\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #89DDFF\">(<\/span><span style=\"color: #82AAFF\">Get-Content<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">-<\/span><span style=\"color: #EEFFFF\">Raw <\/span><span style=\"color: #89DDFF\">$<\/span><span style=\"color: #EEFFFF\">p<\/span><span style=\"color: #89DDFF\">)<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">-replace<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #EEFFFF\">`r`n<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #89DDFF\">,<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #EEFFFF\">`n<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">|<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #82AAFF\">Set-Content<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">-<\/span><span style=\"color: #EEFFFF\">NoNewline <\/span><span style=\"color: #89DDFF\">$<\/span><span style=\"color: #EEFFFF\">p<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><code>-Raw<\/code> keeps the file as one string, <code>-NoNewline<\/code> stops <code>Set-Content<\/code> from appending a trailing CRLF. Works fine in PowerShell 7 (default: UTF-8 without BOM). In Windows PowerShell 5.1 both cmdlets default to ANSI, and <code>-Encoding UTF8<\/code> writes a BOM \u2013 check the result there.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>**dos2unix \/ sed**<\/strong> \u2013 Git Bash (part of Git for Windows) ships <code>dos2unix<\/code>, and so do most Linux boxes and WSL distributions:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8220;`bash<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#EEFFFF;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#304047;color:#d5ffff\">PowerShell<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#EEFFFF;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>dos2unix deploy.sh\nsed -i 's\/\\r$\/\/' deploy.sh<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme\" style=\"background-color: #263238\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #EEFFFF\">dos2unix deploy.sh<\/span><\/span>\n<span class=\"line\"><span style=\"color: #EEFFFF\">sed <\/span><span style=\"color: #89DDFF\">-<\/span><span style=\"color: #EEFFFF\">i <\/span><span style=\"color: #89DDFF\">&#39;<\/span><span style=\"color: #C3E88D\">s\/\\r$\/\/<\/span><span style=\"color: #89DDFF\">&#39;<\/span><span style=\"color: #EEFFFF\"> deploy.sh<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>## Better: don&#8217;t create CRLF in the first place<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>### VS Code<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The status bar shows <code>CRLF<\/code> or <code>LF<\/code> in the bottom right corner \u2013 click it to switch the current file, then save. The default for new files is set in <code>settings.json<\/code>, either globally or just for shell scripts:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#EEFFFF;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#304047;color:#d5ffff\">JSON<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#EEFFFF;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>{\n  \/\/ all new files\n  \"files.eol\": \"\\n\",\n\n  \/\/ or only shell scripts\n  \"&#91;shellscript&#93;\": {\n    \"files.eol\": \"\\n\"\n  }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme\" style=\"background-color: #263238\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #89DDFF\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #EEFFFF\">  <\/span><span style=\"color: #546E7A; font-style: italic\">\/\/ all new files<\/span><\/span>\n<span class=\"line\"><span style=\"color: #EEFFFF\">  <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #C792EA\">files.eol<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #89DDFF\">:<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #EEFFFF\">\\n<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #89DDFF\">,<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #EEFFFF\">  <\/span><span style=\"color: #546E7A; font-style: italic\">\/\/ or only shell scripts<\/span><\/span>\n<span class=\"line\"><span style=\"color: #EEFFFF\">  <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #C792EA\">&#91;shellscript&#93;<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #89DDFF\">:<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #EEFFFF\">    <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #FFCB6B\">files.eol<\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #89DDFF\">:<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #EEFFFF\">\\n<\/span><span style=\"color: #89DDFF\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #EEFFFF\">  <\/span><span style=\"color: #89DDFF\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #89DDFF\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>**Note:**<\/strong> <code>files.eol<\/code> only applies to <strong>**new**<\/strong> files. Existing files keep their line endings.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>### git<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The personal setting:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#EEFFFF;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#304047;color:#d5ffff\">Bash<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#EEFFFF;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>git config --global core.autocrlf input<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme\" style=\"background-color: #263238\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #FFCB6B\">git<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">config<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">--global<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">core.autocrlf<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">input<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><code>input<\/code> converts CRLF to LF on commit and leaves the files alone on checkout. The Git for Windows installer defaults to `true`, which checks files out with CRLF \u2013 a common way CRLF ends up in your scripts in the first place.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The team-wide solution is a <code>.gitattributes<\/code> file in the repository. It is versioned and wins over the local <code>core.autocrlf<\/code> of every clone:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#EEFFFF;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#304047;color:#d5ffff\">Bash<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#EEFFFF;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>* text=auto eol=lf\n*.bat text eol=crlf\n*.cmd text eol=crlf<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme\" style=\"background-color: #263238\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #89DDFF\">*<\/span><span style=\"color: #EEFFFF\"> text=auto eol=lf<\/span><\/span>\n<span class=\"line\"><span style=\"color: #89DDFF\">*<\/span><span style=\"color: #EEFFFF\">.bat text eol=crlf<\/span><\/span>\n<span class=\"line\"><span style=\"color: #89DDFF\">*<\/span><span style=\"color: #EEFFFF\">.cmd text eol=crlf<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><code>text=auto<\/code> lets git detect binary files and leave them alone, <code>eol=lf<\/code> enforces LF in the working tree \u2013 on Windows, too. Batch files keep CRLF, because <code>cmd.exe<\/code> can stumble over LF-only files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Files that are already committed with CRLF get fixed with:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#EEFFFF;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#304047;color:#d5ffff\">Bash<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#EEFFFF;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>git add --renormalize .\ngit commit -m \"Normalize line endings\"<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme\" style=\"background-color: #263238\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #FFCB6B\">git<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">add<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">--renormalize<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FFCB6B\">git<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">commit<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #C3E88D\">-m<\/span><span style=\"color: #EEFFFF\"> <\/span><span style=\"color: #89DDFF\">&quot;<\/span><span style=\"color: #C3E88D\">Normalize line endings<\/span><span style=\"color: #89DDFF\">&quot;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">This fixes the repository. Your own working copy keeps the CRLF files until they are checked out again \u2013 or until you run the one-liner from above. `git ls-files &#8211;eol` shows the line endings of every file in the index (`i\/`) and in the working tree (`w\/`).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>## In summary<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8211; <strong>**PowerShell one-liner:**<\/strong> no extra tools, leaves everything but the line endings alone (a UTF-8 BOM excepted) \u2013 use absolute paths and mind the encoding.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8211; <strong>**<code>dos2unix<\/code><\/strong> <strong>\/<\/strong> <strong><code>sed<\/code>:**<\/strong> the classics, whenever Git Bash, WSL or a Linux shell is at hand.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8211; <strong>**VS Code<\/strong> <strong><code>files.eol<\/code>:**<\/strong> prevents CRLF in new files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8211; <strong>**<code>.gitattributes<\/code><\/strong> <strong>with<\/strong> <strong><code>eol=lf<\/code>:**<\/strong> the team-wide fix that makes the problem go away for good.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Although this topic has been discussed so often, I think I can still contribute something regarding CRLF\/LF. You write a shell script on Windows, copy it to a Linux server, run it \u2013 and get: (Newer bash versions are even less helpful: cannot execute: required file not found.) The culprit is Windows line endings: **CRLF** (\\r\\n) instead of **LF** (\\n). Bash treats the trailing \\r as part of the command. If dos2unix is not at hand, PowerShell handles the conversion in a single line that isn&#8217;t particularly easy to remember: ## How it works &#8211; [IO.File]::ReadAllText($p) reads the whole file into a single string \u2013 line endings included. &#8211; -replace &#8220;`r`n&#8221;, &#8220;`n&#8221; replaces every CRLF with LF. Inside double quotes, `r and `n are PowerShell escape sequences for CR and LF. &#8211; [IO.File]::WriteAllText() writes the string back as it is. Why not simply Get-Content \/ Set-Content? Without -Raw, Get-Content splits the file into lines and drops the line endings, and Set-Content joins them again with the Windows default \\r\\n \u2013 exactly what you wanted to get rid of. ## Three gotchas **1. Use an absolute path.** .NET resolves relative paths against the process working directory, not against your current PowerShell location. After a Set-Location, .\\deploy.sh may point somewhere else \u2013 or nowhere. Resolve it first: **2. Mind the encoding.** ReadAllText() assumes UTF-8 (unless a BOM says otherwise), WriteAllText() writes UTF-8 **without** BOM. For UTF-8 or plain ASCII scripts that is exactly what you want \u2013 a UTF-8 BOM is dropped on the way, which Linux tools appreciate anyway. **ANSI files (Windows-1252) with umlauts, however, get corrupted:** \u00fc turns into \ufffd. Pass the encoding explicitly in that case: **3. The whole file goes into memory.** Fine for scripts and config files, not for multi-GB logs. ## Converting a whole directory FullName is always absolute (gotcha #1 solved), and files that are already clean are not touched. .Replace() is the plain string method \u2013 a literal replacement without the regex engine, same result. ## Alternatives **PowerShell cmdlets:** -Raw keeps the file as one string, -NoNewline stops Set-Content from appending a trailing CRLF. Works fine in PowerShell 7 (default: UTF-8 without BOM). In Windows PowerShell 5.1 both cmdlets default to ANSI, and -Encoding UTF8 writes a BOM \u2013 check the result there. **dos2unix \/ sed** \u2013 Git Bash (part of Git for Windows) ships dos2unix, and so do most Linux boxes and WSL distributions: &#8220;`bash ## Better: don&#8217;t create CRLF in the first place ### VS Code The status bar shows CRLF or LF in the bottom right corner \u2013 click it to switch the current file, then save. The default for new files is set in settings.json, either globally or just for shell scripts: **Note:** files.eol only applies to **new** files. Existing files keep their line endings. ### git The personal setting: input converts CRLF to LF on commit and leaves the files alone on checkout. The Git for Windows installer defaults to `true`, which checks files out with CRLF \u2013 a common way CRLF ends up in your scripts in the first place. The team-wide solution is a .gitattributes file in the repository. It is versioned and wins over the local core.autocrlf of every clone: text=auto lets git detect binary files and leave them alone, eol=lf enforces LF in the working tree \u2013 on Windows, too. Batch files keep CRLF, because cmd.exe can stumble over LF-only files. Files that are already committed with CRLF get fixed with: This fixes the repository. Your own working copy keeps the CRLF files until they are checked out again \u2013 or until you run the one-liner from above. `git ls-files &#8211;eol` shows the line endings of every file in the index (`i\/`) and in the working tree (`w\/`). ## In summary &#8211; **PowerShell one-liner:** no extra tools, leaves everything but the line endings alone (a UTF-8 BOM excepted) \u2013 use absolute paths and mind the encoding. &#8211; **dos2unix \/ sed:** the classics, whenever Git Bash, WSL or a Linux shell is at hand. &#8211; **VS Code files.eol:** prevents CRLF in new files. &#8211; **.gitattributes with eol=lf:** the team-wide fix that makes the problem go away for good.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,37,38,27],"tags":[46,78],"class_list":["post-1234","post","type-post","status-publish","format-standard","hentry","category-git","category-korn-shell","category-powershell","category-windows-bash","tag-bash","tag-powershell"],"_links":{"self":[{"href":"https:\/\/techno.slomka.biz\/index.php?rest_route=\/wp\/v2\/posts\/1234","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/techno.slomka.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/techno.slomka.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/techno.slomka.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/techno.slomka.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1234"}],"version-history":[{"count":1,"href":"https:\/\/techno.slomka.biz\/index.php?rest_route=\/wp\/v2\/posts\/1234\/revisions"}],"predecessor-version":[{"id":1235,"href":"https:\/\/techno.slomka.biz\/index.php?rest_route=\/wp\/v2\/posts\/1234\/revisions\/1235"}],"wp:attachment":[{"href":"https:\/\/techno.slomka.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/techno.slomka.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/techno.slomka.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}