簡體   English   中英

用文件名替換多個文件中的字符串

[英]Replacing a String In Multiple Files With Their Filename

所以我有一個文本文件,我想改變字符串到文件本身的名字逐一unamed整個大文件夾,延伸除外。

到目前為止,憑借我的清道夫技能,我想出了以下內容,但它沒有給出我正在尋找的內容,因為它將名稱更改為每個收集的文件

$path = "*.txt"
$filename = Get-Item $path | Select-Object -ExpandProperty BaseName
$Change = Get-Content $path
$Change | ForEach-Object {$_ -Replace "unamed", $filename} | Set-Content $path

所以基本上是這樣的

此文件的名稱未命名。

正在變得

該文件的名稱是 File1Name File2Name File3Name。

還有一個我遇到的附帶問題,其中所有文件的結果合並到一個文件中(因此文件 1 的內容現在也將包含所有其他文件的內容)。 我怎樣才能得到我尋求的結果哦,明智的人?

如果有辦法用常規命令行而不是 powershell 解決這個問題,那么我也會解決這個問題(我發現了這個問題,但是 replace_string 是無效命令有問題? 用 filename 替換文件中的靜態字符串的批處理腳本

像這樣的東西?

Get-ChildItem -Filter "*.txt" | ForEach-Object {
  $Path=$_.FullName; (Get-Content $Path) -replace 'unamed', $_.BaseName | Set-Content $Path 
}

世界語的答案效果很好並且與 PSv2 兼容; 這是一個更快但更占用內存的 PSv3+ 解決方案:

Get-Content -Raw *.txt | ForEach-Object {
  $_ -replace 'unamed', [IO.Path]::GetFileNameWithoutExtension($_.PSPath) |
    Set-Content $_.PSPath
}
  • 除非您有特殊的文件匹配需求,例如遞歸查找文件或需要排除文件或需要按文件屬性進行匹配,否則您不需要Get-Item / Get-ChildItem來枚舉感興趣的文件 - 您可以傳遞通配符模式如*.txt直接到Get-Content的(隱含) -Path參數。

  • Get-Content -Raw (PSv3+) 將匹配*.txt的每個文件的全部內容作為一個整體讀取到內存,作為單個字符串

    • 注意:由於每個文件在輸出到管道之前都是作為一個整體讀取的,因此此解決方案可能不適用於非常大的文件,具體取決於可用內存。
  • Get-Content使用有關字符串來源的信息裝飾它輸出的字符串,以便返回的每個字符串的.PSPath屬性包含讀取該字符串的文件的完整文件名。

  • [IO.Path]::GetFileNameWithoutExtension($_.PSPath)從路徑中提取文件名根目錄(沒有擴展名的文件名)

    • 直接使用 .NET 是必要的,不幸的是, Split-Path cmdlet 不允許您在 Windows PowerShell 中執行此操作,但在 PowerShell Core 中,您可以改用Split-Path -LeafBase

警告Set-Content使用默認編碼(Windows PowerShell:“ANSI”;PowerShell Core :無 BOM 的 UTF-8),它可能與輸入編碼相同,也可能不同; 根據需要使用-Encoding參數。


至於你嘗試什么

$filename = Get-Item $path | Select-Object -ExpandProperty BaseName

$filename現在包含文件名根(基本名稱)的數組

$Change = Get-Content $path

$Change現在包含一個數組,其元素是來自所有輸入文件的行。

$Change | ForEach-Object {$_ -Replace "unamed", $filename} | Set-Content $path

  • 因為$Change是一個單一的平面數組,所以你已經失去了數組元素到文件或源的分區,並且Set-Content所有行發送到目標文件。

  • 因為$filename是一個數組,-replace的第二個 RHS 操作數只支持標量(單個字符串), $_ -replace "unamed", $filename導致$filename被轉換為單個字符串,這是一個空格分隔的數組元素的串聯(文件名根)。

  • Set-Content $Path恰好將行的平面(修改)數組寫入多個文件,即與$Path中的通配符表達式匹配的現有文件, *.txt

    • 如上所述,輸入Set-Content接收為輸入的文件線的級聯,因此,所有輸出文件接收級聯(經修飾)內容從所有輸入文件(名稱匹配通配符模式的所有文件*.txt

    • 順便說一句: Set-Content *.txt允許將相同的內容寫入多個預先存在的輸出文件,這是一個令人驚訝且可能具有破壞性的功能,可以說是不支持的 - 請參閱此 GitHub 討論

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM