Пакетное изменение каталога с помощью Powershell - PullRequest
2 голосов
/ 05 апреля 2019

Мне нужно обновить каталог во многих текстовых файлах

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, но результаты странные: либо все файлы имеют одинаковый результат, либо все новые каталоги (продаются ниже)

Я хочу обновить oldpath в newpath во всех файлах.Код следующий:

$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 ]

2 голосов
/ 05 апреля 2019

Мне немного неясно, каким должен быть конечный контент.Это 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...
2 голосов
/ 05 апреля 2019

С поисками вы можете точно определить, куда вставить текст, не повторяя шаблон поиска.

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\ снова.
1 голос
/ 05 апреля 2019

вот способ сделать работу. [ ухмыляется ] что он делает ...

  • между #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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...