Сценарий Powershell, чтобы найти имя файла в файле и переместить его в другой каталог - PullRequest
0 голосов
/ 17 января 2019

Я сейчас пишу сценарий powershell. Предполагается просматривать все файлы в каталоге и перемещать их в разные каталоги в зависимости от их содержимого. Теперь в некоторых из этих файлов указаны имена файлов, например, связанных растровых изображений. Как я могу сделать так, чтобы, если он видит связанный файл, он перемещался в ту же папку?

Пока это мой сценарий, он распределяет файлы по 2 различным каталогам, основываясь на том, содержат ли они слова, заданные в $ pattern1 и $ pattern2.

$source = 'Z:\Documents\16_Med._App\Aufträge\RuheEKG_24HBP_Skript\Ursprung_test'
$destination = 'Z:\Documents\16_Med._App\Aufträge\RuheEKG_24HBP_Skript\24BHD'
$toDelete = 'Z:\Documents\16_Med._App\Aufträge\RuheEKG_24HBP_Skript\ToDelete'
$pattern1 = '24BHD'
$pattern2 = 'RuheEKG'

$hans = Get-ChildItem $source  

foreach($item in $hans) {
    if (Select-String -list -pattern $pattern1 -path $item.fullname) {
        Move-Item -Path $item.fullname -Destination $destination}
        Else {
        Move-Item -Path $item.fullname -Destination $toDelete}


}

At the end of line 31, you see the associated Bitmap file.

В конце строки 31 вы видите связанный файл растрового изображения. Мне нужен скрипт, чтобы распознать его как другой файл, найти его и переместить в тот же каталог, в котором находится файл, в котором он находится.

Буду признателен за любую помощь!

Ответы [ 3 ]

0 голосов
/ 17 января 2019

Если у вас есть список сопоставляемых шаблонов, и вы можете гарантировать, что шаблоны всегда будут совпадать, а не случайно совпадать с чем-то другим, вы можете использовать оператор switch с таким количеством совпадений и назначений шаблонов, которое вам нравится.

Возможно, вам понадобится построить место назначения на основе имени исходного файла, в данном случае я грубо жестко закодировал пути назначения, как примеры:

$hans = Get-ChildItem $source

foreach($item in $hans)
{
    switch($item.FullName)
    {
        { $_ -match '24BHD' }        { $destination = 'Z:\24BHD_Destination' }
        { $_ -match 'RuheEKG' }      { $destination = 'Z:\RuheEKG_Destination' }
        { $_ -match 'OtherPattern' } { $destination = 'Z:\OtherCode_Destination' }

        default { Write-Host "Match not found for file $($item.FullName)" }
    }

    Move-Item $item.FullName $destination
}
0 голосов
/ 18 января 2019

Я предполагаю, что после перемещения файлов и связанных растровых файлов вы также хотели бы, чтобы файл содержал новые пути к файлам для этих ссылочных файлов.

Кроме того, поскольку ваши шаблоны на самом деле не являются регулярными выражениями, я использовал параметр -SimpleMatch в Select-String.

Этот код должен делать именно это.

$source      = 'Z:\Documents\16_Med._App\Aufträge\RuheEKG_24HBP_Skript\Ursprung_test'
$destination = 'Z:\Documents\16_Med._App\Aufträge\RuheEKG_24HBP_Skript\24BHD'
$toDelete    = 'Z:\Documents\16_Med._App\Aufträge\RuheEKG_24HBP_Skript\ToDelete'
$pattern1    = '24BHD'
$pattern2    = 'RuheEKG'

# create the destination paths if they do not exist
if (!(Test-Path -Path $destination -PathType Container)) {
    Write-Host "Creating folder '$destination'"
    New-Item -Path $destination -ItemType 'Directory' -Force | Out-Null
}
if (!(Test-Path -Path $toDelete -PathType Container)) {
    Write-Host "Creating folder '$toDelete'"
    New-Item -Path $toDelete -ItemType 'Directory' -Force | Out-Null
}

# get an array of full path and filenames.
# if they all have the same extension, it would be wise to add the '-Filter' parameter..
$allFiles = @(Get-ChildItem $source -File | Select-Object -ExpandProperty FullName)

foreach($file in $allFiles) {
    # get the file content as array so we can reuse it and update the line(s) with the new bitmap path(s)
    $content = Get-Content -Path $file

    # first decide on the destination. '-Quit' returns $true or $false
    # if both $pattern1 AND $pattern2 are present, move stuff to $destination
    if (($content | Select-String -Pattern $pattern1 -SimpleMatch -Quiet) -and 
        ($content | Select-String -Pattern $pattern2 -SimpleMatch -Quiet)) {
        $dest = $destination
    }
    else {
        $dest = $toDelete
    }

    # next check if the file contains path(s) for referenced (bitmap) file((s)
    $refCount = 0
    $content | Select-String -Pattern '(^.*)([A-Z]:\\.+$)' -AllMatches | ForEach-Object {
        # each '$_' automatic variable in here holds a MatchInfo object.
        # see: https://docs.microsoft.com/en-us/dotnet/api/microsoft.powershell.commands.matchinfo?view=pscore-6.0.0

        $prefix  = $_.Matches[0].Groups[1].Value   # get the prefix of the line (something like '0619154')
        $refPath = $_.Matches[0].Groups[2].Value   # get the bitmap file path

        if (Test-Path -Path $refPath -PathType Leaf) {
            Write-Host "Moving referenced file '$refPath' to '$dest'"
            Move-Item -Path $refPath -Destination $dest -Force
            # recreate the line to match the new location of the bitmap file
            Write-Host "Updating path in '$file' to '$refPath'"
            $refFile = Split-Path $refPath -Leaf
            $refPath = Join-Path -Path $dest -ChildPath $refFile
            $content[$_.LineNumber -1] = $prefix + $refPath
            $refCount++
        }
        else {
            Write-Warning "Referenced file '$refPath' not found"
        }
        if ($refCount) {
            # we handled referenced files, so write the new content back to the original file
            Set-Content -Path $file -Value $content -Force
        }
    }

    # finally move the file to its new destination
    Write-Host "Moving file '$file' to '$dest'"
    Move-Item -Path $file -Destination $dest -Force
}


EDIT

Согласно вашим комментариям:

Я проверил это, как показано ниже.

Я создал пару папок на диске D: и поместил туда файлы:

+---Fnkraf
    \---Bitmaps
    |       PIC0053.BMP
    |       PIC0057.BMP
    |       PIC0571.BMP
    |       PIC0572.BMP
    |
    \---MasterFiles
            File1.txt
            File2.txt
            File3.txt

Папка Bitmaps содержит ссылки на растровые файлы.
В папку MasterFiles я положил эти файлы:

FILE1.TXT
Этот файл действителен, поскольку он содержит оба шаблона ключевых слов и имеет два ссылочных файла растрового изображения. Оба упомянутых файла присутствуют. Они перейдут в папку 24BHD.

24BHD
RuheEKG

01091521
0249153EKG 10 Sekunden
0619154D:\Fnkraf\Bitmaps\PIC0053.BMP
0619155D:\Fnkraf\Bitmaps\PIC0057.BMP
0118410HF

file2.txt
Этот файл действителен, поскольку он содержит оба шаблона ключевых слов и имеет два ссылочных файла растрового изображения. Один из которых выдаст предупреждение, потому что его нельзя найти. Они перейдут в папку 24BHD.

24BHD
RuheEKG

01091521
0249153EKG 15 Sekunden
0719154D:\Fnkraf\Bitmaps\PIC0571.BMP
0719157D:\Fnkraf\Bitmaps\DOESNOTEXIST.BMP
0118410HG

file3.txt
Этот файл недействителен, поскольку содержит только один шаблон ключевых слов. Он имеет доступный для поиска файл растрового изображения. Они должны идти в папку toDelete

25BHD
RuheEKG

01091521
0249153EKG 17 Sekunden
0619154D:\Fnkraf\Bitmaps\PIC0572.BMP
0118410HG

После запуска скрипта это результат:

+---Fnkraf
    \---24BHD
    |       File1.txt
    |       File2.txt
    |       PIC0053.BMP
    |       PIC0057.BMP
    |       PIC0571.BMP
    |
    +---Bitmaps
    +---MasterFiles
    \---ToDelete
            File3.txt
            PIC0572.BMP

Можно видеть, что и папка назначения 24BHD, и папка toDelete созданы, и главные файлы File1.txt и File2.txt оказались в месте назначения вместе с ссылочными файлами растровых изображений.
File3.txt не прошел проверку шаблона, как ожидалось, и был перемещен в папку toDelete, снова со ссылочным файлом растрового изображения.

Теперь, если вы откроете перемещенные текстовые файлы, вы увидите, что пути к ссылочным файлам были обновлены в соответствии с новым местоположением растровых изображений.

FILE1.TXT

24BHD
RuheEKG

01091521
0249153EKG 10 Sekunden
0619154D:\Fnkraf\24BHD\PIC0053.BMP
0619155D:\Fnkraf\24BHD\PIC0057.BMP
0118410HF

То же самое было сделано для других файлов. Единственная ссылка, которая была обновлена ​​ NOT , - это файл растрового изображения, который не найден в File2.txt :

24BHD
RuheEKG

01091521
0249153EKG 15 Sekunden
0719154D:\Fnkraf\24BHD\PIC0571.BMP
0719157D:\Fnkraf\Bitmaps\DOESNOTEXIST.BMP
0118410HG

Надеюсь, это все объясняет.

0 голосов
/ 17 января 2019

Мне приходит в голову много вопросов, например:

  • Всегда ли путь к файлу всегда находится в конце строки?
  • Есть ли один путь к файлу на файл или может быть, что есть еще строки, содержащие путь?

Предполагая, что ответ на вышеуказанные вопросы - да, пути к файлам можно проанализировать из файла, подобного этому:

foreach($item in $hans) {
    $mat = $item | Select-String -Pattern '.:\\.+'
    foreach($m in $mat) {
        $m.Matches.Value
    }
}

.:\\.+ - это регулярное выражение, которое ищет последовательность буквы диска, двоеточия, обратной косой черты и захватывает все, что за ней, в одной строке.

Во многих случаях требуется, чтобы такой скрипт синтаксического анализа работал без ошибок. Регулярные выражения и Select-String - ваши друзья, но прежде чем вы их действительно узнаете, требуется некоторое время :-) Проверьте / напишите свой RegEx на https://regex101.com/ Я использую его большую часть времени при написании регулярных выражений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...