使用Powershell批量修改目录

时间:2019-04-05 00:44:19

标签: powershell

我需要更新许多txt文件中的目录

Input files:
1.txt
using c:\data\1.dta
its own data

2.txt
using c:\data\2.dta
its own data

3.txt
using c:\data\3.dta
its own data

Expected Output files:
1.txt
using C:\Data\Subfile\1.dta
its own data

2.txt
using C:\Data\Subfile\2.dta
its own data

3.txt
using C:\Data\Subfile\3.dta
its own data

我尝试过-replace,但是结果很奇怪:所有文件都具有相同的结果,或者具有所有新目录(下面叫卖)

我想将所有文件中的旧路径更新为新路径。代码如下:

$pathway='C:Data\Subfile\*.txt'
$oldpath='c:\\data\\'
$newpath='C:\Data\Subfile\'
$content=Get-Content -path $pathway

方法1:

$newline=((Get-Content -path $pathway -TotalCount 1) -replace $oldpath,$newpath)
$content[0]= $newline

This method will include all updated directories in every file:
Wrong output:
1.txt
using C:\Data\Subfile\1.txt
using C:\Data\Subfile\2.txt
using C:\Data\Subfile\3.txt
its own data

2.txt
using C:\Data\Subfile\1.txt
using C:\Data\Subfile\2.txt
using C:\Data\Subfile\3.txt
its own data

方法2:

$content[0]=$content[0]-replace $oldpath,$newpath

This method will cause all file has the same new directory:
Wrong output:
1.txt
using C:\Data\Subfile\1.txt 
its own data

2.txt
using C:\Data\Subfile\1.txt 
its own data

3.txt
using C:\Data\Subfile\1.txt 
its own data

$content | Set-Content -Path $pathway

有人可以帮我吗?我希望每个文件都有其对应的新目录。对于1.txt,我想要C:\ Data \ Subfile \ 1.txt,对于2.txt,我想要C:\ Data \ Subfile \ 2.txt等。

非常感谢!

3 个答案:

答案 0 :(得分:2)

我不清楚您希望最终内容是什么。是using C:\Data\Subfile\1.txt还是using C:\Data\Subfile\1.dta?我认为您正在要求以下内容,但如果不告诉我。您可能会遇到速度/性能问题,具体取决于文件的大小。

如果这些是您的输入文件及其内容:

C:\data\Subfile\1.txt
  using c:\data\1.dta
  its own data...

C:\data\Subfile\2.txt
  using c:\data\2.dta
  its own data...

C:\data\Subfile\3.txt
  using c:\data\3.dta
  its own data...

然后这个:

Get-ChildItem c:\data\Subfile\*.txt | Foreach-Object{
    #Read in all content lines and replace c:\data\ with c:\data\subfile
    $content = Get-Content $_.FullName | %{$_ -replace 'c:\\Data\\', 'c:\Data\Subfile\' }
    #write the new data to file
    $content | Set-Content $_.FullName
}

结果如下:

C:\data\Subfile\1.txt
  using c:\Data\Subfile\1.dta
  its own data...

C:\data\Subfile\2.txt
  using c:\Data\Subfile\2.dta
  its own data...

C:\data\Subfile\3.txt
  using c:\Data\Subfile\3.dta
  its own data...

答案 1 :(得分:2)

使用lookarounds,您可以精确定义插入文本的位置,而无需重复搜索模式。

foreach ($File in Get-ChildItem 'C:\Data\Subfile\*.txt'){
    (Get-Content $File -raw) -replace "(?<=C:\\data\\)(?=\d\.dta)","Subfile\" |
     Set-Content $File
}
  • "(?<=C:\\data\\)是零长度断言之后的积极回溯,
  • (?=\d\.dta)是一个正向提前零长度断言,
  • 替换文本插入这两个文本之间。
  • 与其他方法相比,它更安全,因为它可以重复执行而无需再次插入Subfile\

答案 2 :(得分:1)

这是完成任务的一种方法。 [咧嘴]它的作用...

  • #region/#endregion标记之间只是为了使文件可以使用
  • 读取文件列表
  • 通过该列表重复
  • 加载每个内容
  • 用新目录替换旧目录
  • 最终写出新内容

这是代码...

#region - Make files to work with
$Null = New-Item -Path "$env:TEMP\TestFiles" -ItemType Directory -ErrorAction SilentlyContinue

$1stFileName = "$env:TEMP\TestFiles\1.txt"
$1stFileContent = @'
using c:\data\1.dta
its own data
'@ -split [System.Environment]::NewLine |
    Set-Content -LiteralPath $1stFileName

$2ndFileName = "$env:TEMP\TestFiles\2.txt"
$2ndFileContent = @'
using c:\data\2.dta
its own data
'@ -split [System.Environment]::NewLine |
    Set-Content -LiteralPath $2ndFileName

$3rdFileName = "$env:TEMP\TestFiles\3.txt"
@'
using c:\data\3.dta
its own data
'@ -split [System.Environment]::NewLine |
    Set-Content -LiteralPath $3rdFileName
#endregion - Make files to work with

$OldDir = 'c:\data'
$NewDir = 'c:\data\SubDir'

$SourceDir = "$env:TEMP\TestFiles"

$FileList = Get-ChildItem -LiteralPath $SourceDir -Filter '*.txt' -File

foreach ($FL_Item in $FileList)
    {
    $NewContent = Get-Content -LiteralPath $FL_Item.FullName |
        ForEach-Object {
            $_.Replace($OldDir, $NewDir)
            }
    $NewContent |
        Set-Content -LiteralPath $FL_Item.FullName
    }

脚本运行前后文件1.txt的内容...

# before ...
using c:\data\1.dta
its own data    

# after ...
using c:\data\SubDir\1.dta
its own data