Powershell - изменение файла Дата создания и дата изменения на основе имени файла - PullRequest
0 голосов
/ 19 мая 2019

У меня есть много отсканированных файлов PDF-документов, в которых указан файл с указанной датой. Например:

FileA_2017-10-15.pdf
FileB_2016-04-08.pdf
FileC_2018-01-30.pdf

некоторые файлы также отформатированы с подчеркиванием в конце, например ...

FileD_2018-01-30_1.pdf
FileE_2018-01-30_2.pdf

Есть даже несколько, которые имеют два подчеркивания до даты, такие как ...

FileF_Example_2018-01-30_1.pdf
FileG_Example_2018-01-30_2.pdf

К сожалению, дата их сканирования отличается от фактической даты документа. Таким образом, атрибуты «Дата создания» и «Дата изменения» отличаются от того, что показано в имени файла.

Я бы хотел, чтобы скрипт, который я мог запустить, изменил «Дата создания» и «Дата изменения» в соответствии с именем файла.

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

$Directory = "C:\TestFolder"
$DateFormat = "yyyy-MM-dd"


foreach ($file in (Get-ChildItem $Directory)) {
    $date_from_file=GetFileName::[datetime])

    $file.CreationTime = $date_from_file
    $file.LastAccessTime = $date_from_file
    $file.LastWriteTime = $date_from_file

    Write-Host ($file.Name + " - " + $date_from_file)
    }

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

Редактировать Интересно, можно ли добавить сценарий, чтобы он мог также включать файлы в подпапки. Возможно, его можно было бы написать так, чтобы он рассматривал только файлы в папке, если Дата изменения в папке - сегодня. Я хотел бы запустить это в родительской папке, которая потенциально может иметь много подпапок, и если у этих папок нет «Дата изменения» сегодня, то он должен пропустить файлы в этой папке. Я думал, что это может ускорить процесс. Открыты для мыслей и спасибо за помощь!

Ответы [ 2 ]

1 голос
/ 19 мая 2019

[ редактировать - так как OP получает очень странные ошибки с моим предложенным исправлением - ошибки, которые я не могу воспроизвести с примерами данных - я изменил этот ответ на полный предлагаемый код. edit 2 - добавлены новые варианты имен файлов и код для их обработки.
edit 3 - изменен с разделения на совпадение с регулярным выражением, так как пример данных изменился еще раз. [* вздох ... *] ]

вы на самом деле не создаете объект datetime, который вам нужен. строка $date_from_file= на самом деле не делает ничего, кроме создания красных сообщений об ошибках ... [ ухмылка ]

заменить эту строку ...

$date_from_file=GetFileName::[datetime])

... с этой строкой ...

$date_from_file = [datetime]::ParseExact($File.BaseName.Split('_')[-1], $DateFormat, $Null)

... и ваша переменная $date_from_file будет содержать правильный объект [datetime], который будет работать в ваших назначениях.

Я бы, вероятно, изменил бы последовательность этих назначений, чтобы поставить $file.LastAccessTime = $date_from_file LAST, чтобы он не изменился к следующей строке.

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


Вот полный сценарий вместе с тем, что он делает -

что он делает ...

  • устанавливает местоположение и формат даты для использования
  • создает набор тестовых файлов из имен файлов примеров OP
  • получает файлы из источника
  • преобразует .BaseName в [datetime] объект
  • присваивает значения .CreationTime, .LastWriteTime, & .LastAccessTime дате / времени из имени файла
  • отображает измененные значения

вот код ...

$Directory = $env:TEMP
$DateFormat = "yyyy-MM-dd"

# create some test files
$TestFileList = @(
    'FileA_2017-10-15.pdf'
    'FileB_2016-04-08.pdf'
    'FileC_2018-01-30.pdf'
    'FileD_2019-09-09_1.pdf'
    'FileE_2015-05-05_2.pdf'
    )
foreach ($TFL_Item in $TestFileList)
    {
    $Null = New-Item -Path $Directory -Name $TFL_Item -ItemType File -Force
    }

$FileList = Get-ChildItem -LiteralPath $Directory -Filter '*.pdf' -File
foreach ($FL_Item in $FileList) {

    # removed split, added regex match to work with ever-growing list of variant file names
    $Null = $FL_Item.BaseName -match '_(?<DateString>\d{4}-\d{2}-\d{2})'
    $DateString = $Matches.DateString
    $date_from_file = [datetime]::ParseExact($DateString, $DateFormat, $Null)

    $FL_Item.CreationTime = $date_from_file
    $FL_Item.LastWriteTime = $date_from_file
    $FL_Item.LastAccessTime = $date_from_file

    # show the resulting datetime info
    '=' * 20
    $CurrentFileInfo = Get-Item -LiteralPath $FL_Item.FullName
    $CurrentFileInfo.FullName
    $CurrentFileInfo.CreationTime
    $CurrentFileInfo.LastWriteTime
    $CurrentFileInfo.LastAccessTime
    }

вывод на экран ...

====================
C:\Temp\FileA_2017-10-15.pdf

2017 October 15, Sunday 12:00:00 AM
2017 October 15, Sunday 12:00:00 AM
2017 October 15, Sunday 12:00:00 AM
====================
C:\Temp\FileB_2016-04-08.pdf
2016 April 08, Friday 12:00:00 AM
2016 April 08, Friday 12:00:00 AM
2016 April 08, Friday 12:00:00 AM
====================
C:\Temp\FileC_2018-01-30.pdf
2018 January 30, Tuesday 12:00:00 AM
2018 January 30, Tuesday 12:00:00 AM
2018 January 30, Tuesday 12:00:00 AM
====================
C:\Temp\FileD_2019-09-09_1.pdf
2019 September 09, Monday 12:00:00 AM
2019 September 09, Monday 12:00:00 AM
2019 September 09, Monday 12:00:00 AM
====================
C:\Temp\FileE_2015-05-05_2.pdf
2015 May 05, Tuesday 12:00:00 AM
2015 May 05, Tuesday 12:00:00 AM
2015 May 05, Tuesday 12:00:00 AM

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

1 голос
/ 19 мая 2019

Вы довольно близко, вам нужно

  • отделить часть даты от имени файла и преобразовать ее в [datetime]
  • Я использую RegEx с группой захвата, закрепленной наend $ BaseName
## Q:\Test\2019\05\19\SO_56211626.ps1
$Directory = "C:\TestFolder"

foreach ($file in (Get-ChildItem -Path $Directory -Filter *.pdf)){
    if($File.BaseName -match '_(\d{4}-\d{2}-\d{2})(_\d)?$'){
        $date_from_file= (Get-Date $Matches[1])

        $file.CreationTime   = $date_from_file
        $file.LastAccessTime = $date_from_file
        $file.LastWriteTime  = $date_from_file
        $file | Select-Object Name,CreationTime,LastAccessTime,LastWriteTime
    }
}

Пример вывода:

> Q:\Test\2019\05\19\SO_56211626.ps1

Name                 CreationTime        LastAccessTime      LastWriteTime
----                 ------------        --------------      -------------
FileA_2017-10-15.pdf 2017-10-15 00:00:00 2017-10-15 00:00:00 2017-10-15 00:00:00
FileB_2016-04-08.pdf 2016-04-08 00:00:00 2016-04-08 00:00:00 2016-04-08 00:00:00
FileC_2018-01-30.pdf 2018-01-30 00:00:00 2018-01-30 00:00:00 2018-01-30 00:00:00

Английский язык (en-US) выдает:

Name                 CreationTime           LastAccessTime         LastWriteTime
----                 ------------           --------------         -------------
FileA_2017-10-15.pdf 10/15/2017 12:00:00 AM 10/15/2017 12:00:00 AM 10/15/2017 12:00:00 AM
FileB_2016-04-08.pdf 4/8/2016 12:00:00 AM   4/8/2016 12:00:00 AM   4/8/2016 12:00:00 AM
FileC_2018-01-30.pdf 1/30/2018 12:00:00 AM  1/30/2018 12:00:00 AM  1/30/2018 12:00:00 AM
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...