Я пытаюсь написать скрипт Powershell для инкрементного дифференциального резервного копирования моего компьютера, однако у меня возникают проблемы с интерпретацией Powershell переменных пути к файлу.

$C_P86Files_Name=Get-ChildItem -File -Path 'C:\Program Files (x86)\Test' -Recurse | foreach FullName
$B_P86Files_Name
$MovedFiles=0
$MovedBytes=0

#Out-File -FilePath 'C:\Program Files (x86)\Test\Test.txt' -InputObject $C_P86Files_Name

Get-ChildItem -File 'C:\Program Files (x86)\Test' -Recurse | foreach FullName

for ($i=0; $i -le ($C_P86Files_Name.Length-1); $i++)
{
    $B_P86Files_Name = $C_P86Files_Name[$i] -replace "^C", "B"

    Write-Host "Checking $($C_P86Files_Name[$i])"
    Write-Host "B drive directory: $($B_P86Files_Name[$i])"

    if(((ls $C_P86Files_Name[$i]).LastWriteTime -ne (ls $B_P86Files_Name[$i]).LastWriteTime) -or ((Test-Path $C_P86Files_Name[$i]) -and (!(Test-Path $B_P86Files_Name[$i]))))
    {
        Copy-Item $C_P86Files_Name[$i] -Destination $B_P86Files_Name[$i]
        $MovedFiles++;
        $MovedBytes+=(Get-Item $C_P86Files_Name[$i]).length

        Write-Host "Moved $($C_P86Files_Name[$i]) to $($B_P86Files_Name[$i])"
    }
}

Write-Host "Total data moved: $($MovedBytes)"

Выходные данные заканчиваются тем, что вместо того, чтобы проходить через C:\Program Files (x86)\Test , он пытается перебрать каждую букву этого пути, как если бы это был файл, а затем выполнить соответствующую ошибку (например, он проверяет "C" и затем проверяет «:», затем проверяет «\» и т. д.).

Я попытался добавить экранированные кавычки к переменным в операторе IF, но это ничего не дало.

Выходной файл показывает правильный путь к файлу, поэтому он, кажется, получает правильную информацию. Я не понимаю, почему массив $C_P86Files_Name видимому, использует каждый символ пути в качестве индекса в массиве, а не каждый файлер из Get-ChildItem в качестве индекса в массиве?

2 ответа2

0

Если вы рассматриваете (единственную) строку как массив, она будет использовать индекс в качестве указателя на символ, чтобы предотвратить это использование @() для принудительной обработки массива даже только с одним элементом.

Ваше использование:

Get-ChildItem -File 'C:\Program Files (x86)\Test' -Recurse | foreach FullName

Возвращает строку / массив строк.

Было бы намного проще сохранить их как объект, через который вы могли бы перебрать (и при этом иметь доступ к его свойствам)

$C_P86Files = Get-ChildItem -File -Path 'C:\Program Files (x86)\Test' -Recurse
ForEach ($File in $C_P86Files){
    $B_FullName = $File.FullName -Replace '^C','B'
}
0

Прошел эту проблему. Похоже, нужно объявить другую переменную, чтобы массив имел одну строку на индекс вместо одного символа.

$Files=Get-ChildItem -File -Path "C:\Program Files (x86)\Test" -Recurse | Select-Object -ExpandProperty FullName
$C_P86Files_Name
$B_P86Files_Name
$MovedFiles=0
$MovedBytes=0
Out-File -FilePath "C:\Program Files (x86)\Test\Test.txt" -InputObject $Files

'-----------------------------------------------------------------'

$C_P86Files_Name=$Files
$B_P86Files_Name=$Files

foreach($i in $C_P86Files_Name)
{
    $C_P86Files_Name[$i]
}

for ($i=0; $i -le ($C_P86Files_Name).Length; $i++)
{
    $B_P86Files_Name[$i]=$B_P86Files_Name[$i] -replace "^C", "B"

    Write-Host "C drive directory: $($C_P86Files_Name[$i])"
    Write-Host "B drive directory: $($B_P86Files_Name[$i])"

    if(((ls $C_P86Files_Name[$i]).LastWriteTime -ne (ls $B_P86Files_Name[$i]).LastWriteTime) -or ((Test-Path $C_P86Files_Name[$i]) -and (!(Test-Path $B_P86Files_Name[$i]))))
    {
        Copy-Item $C_P86Files_Name[$i] -Destination $B_P86Files_Name[$i]
        $MovedFiles++;
        $MovedBytes+=(Get-Item $C_P86Files_Name[$i]).length

        Write-Host "Moved $($C_P86Files_Name[$i]) to $($B_P86Files_Name[$i])"
    }
}

Write-Host "Total data moved: $($MovedBytes)"

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .