2025年2月4日 星期二

PowerShell 使用 ssh 驗證本地與遠端檔案的 SHA256 是否一致

PowerShell 使用 ssh 驗證本地與遠端檔案的 SHA256 是否一致

要驗證傳輸到底有沒有傳對用的函式

# 獲取遠端檔案的雜湊值
function Get-RemoteFileHash {
    [CmdletBinding()]
    param ( 
        # 遠端檔案路徑
        [Parameter(Mandatory, ValueFromPipeline)]
        [string]$Path,
        # 遠端登入資訊
        [Parameter(Mandatory)]
        [string]$RemoteLoginInfo,
        # 遠端私鑰
        [Parameter(Mandatory)]
        [string]$IdentityFile,
        # 遠端作業系統
        [Parameter(Mandatory)]
        [ValidateSet('Windows', 'Linux')]
        [string]$RemoteOS
    ) begin {
        # 檢查私鑰是否存在
        if (-not (Test-Path $IdentityFile)) {
            Write-Error "Cannot find path '$IdentityFile' because it does not exist."
        }
        # 定義不同作業系統的雜湊命令
        $hashCommands = @{
            'Windows' = "powershell `"(Get-FileHash -Path ([WildcardPattern]::Escape('$Path')) -Algorithm SHA256 -EA 1).Hash`""
            'Linux'   = "sha256sum '$Path' 2>&1 >/dev/null && sha256sum '$Path' | cut -d' ' -f1 | tr '[:lower:]' '[:upper:]'"
        }
        # SSH 連線參數設定
        $sshParams = @(
            '-oBatchMode=yes'
            "-oIdentityFile=$IdentityFile"
            $RemoteLoginInfo
        )
    } process {
        # 執行遠端雜湊命令
        $hash = & ssh @sshParams $hashCommands[$RemoteOS] 2>&1
        # 檢查 ssh 命令是否成功
        if ($LASTEXITCODE -ne 0) {
            Write-Error "ssh command failed: $hash" 
            return $null
        }
        # 檢查雜湊值格式是否正確 (SHA-256 應為 64 個十六進制字符)
        if (-not ($hash -match '^[A-F0-9]{64}$')) {
            Write-Error "The hash value '$hash' returned from command '$hashCommand' is not a valid SHA-256 format"
            return $null
        }
        return $hash
    }
}


使用範例

Get-RemoteFileHash "/home/chg/work/Tester.bats" `
    -RemoteLoginInfo "chg@192.168.3.53" `
    -IdentityFile "${env:USERPROFILE}\.ssh\id_ed25519" `
    -RemoteOS "Linux"

執行完會自動返回遠端檔案的哈希值,再來比較本地端即可知道是否一致了。




如果是要從 sftp 指令獲取位址可以參考這個

# 解析 SFTP 命令
function ParseSftpCommandPath {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline)]
        [string]$CommandText
    )
    process {
        # 跳過空行和註解
        if (-not ($CommandText -match '\S') -or $CommandText -match '^\s*#') { return }
        # 解析命令行
        $tokens = [regex]::Matches(
            $CommandText.Trim(), '"[^"]+"|[^\s"]+'
        ).Value.Trim('"')
        # 獲取遠端檔案路徑
        if ($tokens[0] -in 'get','put') {
            $paths = $tokens[1..($tokens.Count-1)].Where({ $_ -notmatch '^-' })
            $idx = @{
                'get' = @{local=-1; remote=0}
                'put' = @{local=0; remote=-1}
            }[$tokens[0]]
            [PSCustomObject]@{
                Command = $tokens[0]
                LocalPath = $paths[$idx.local]
                RemotePath = $paths[$idx.remote]
            }
        }
    }
} # "get /home/chg/work/Tester.bats Tester.bats" | ParseSftpCommandPath


2025-02-04 PowerShell 修改檔案日期與時間 (3)

PowerShell 修改檔案日期與時間 (3)

tags: 部落格文章


關於檔案的 修改時間 和 存取時間有什麼差別可以看這篇站內文


字串格式和日期格式怎麼互轉可以參考這一邊



修改檔案日期

代碼開源在這裡: hunandy14/FileDateEditor


快速使用

irm bit.ly/4gkzM5D|iex; Set-FileDate -File "test\file.txt" "2025-2-4"


詳細功能

# 載入函式
irm bit.ly/4gkzM5D|iex;

# 建立日期
Get-Item "test\file.txt" | Set-FileDate "2025-2-4" -Creation

# 修改日期
Get-Item "test\file.txt" | Set-FileDate "2025-2-4" -Write

# 存取日期
Get-Item "test\file.txt" | Set-FileDate "2025-2-4" -Access

# 日期字串
Get-Item "test\file.txt" | Set-FileDate "2025-02-04" -Format "yyyy-MM-dd"


生成測試檔案

irm bit.ly/4gkzM5D|iex; 1..10 | ForEach-Object{
  $idx=$_.ToString('00')
  New-Item -ItemType File -Path "file_2025-02-$idx.txt" |
  Set-FileDate "2025-02-$idx"
}