3

ファイルを解凍するために 7z.exe コマンドを実行しようとして、次のコードを実行しています。

$dir には、もちろんスペースを含むことができるzip ファイルへのパスのユーザー入力が含まれています! そして、下の $dir\temp2 は以前に作成したディレクトリです。

Get-ChildItem -path $dir -Filter *.zip |
ForEach-Object {
    $zip_path = """" + $dir + "\" + $_.name + """"
    $output = " -o""$dir\temp2"""
    &7z e $zip_path $output
}

実行すると、7z.exe から次のようになります。

7-Zip [64] 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18

Processing archive: C:\test dir\test.zip


No files to process

Files: 0
Size:       0
Compressed: 50219965

$zip_path と $output から値をコピーして、独自のコマンドラインを作成すると、機能します!

例えば:

7z e "c:\test dir\test.zip" -o"c:\test output"

これで、CLI で次のコマンドを使用して、PowerShell 内で実行したときに表示される「処理するファイルがありません」という同じメッセージを再現できます

7z e "c:\test dir\test.zip" o"c:\test output"

そのため、PowerShell が -o オプションからダッシュ文字を削除しているようです。はい、7z.exe では -o "C:\test output" ではなく -o"C:\test output" である必要があります。-o パラメータとその値の間にスペースはありません。

私は困惑しています。私は何か間違ったことをしていますか、それとも別の方法でこれを行うべきですか?

4

3 に答える 3

3

-o私は正確な問題を再現することができ、スイッチをエスケープし、引用符をエスケープするなど、さまざまな組み合わせを試しました"

しかし、ある回答で Sysinternals が言及されていたので、 Process Monitorを使用して 7z.exe に渡される形式を調べました。単純なコマンドラインで機能するものは、PowerShell 内では同じようには機能しません。

たとえば、PowerShell 内で cmdline と同じようにパラメーターを構築しようとすると、失敗します。つまり、-o"C:\scripts\so\new folder"機能しません。ただし、-oスイッチを引用符で囲むと、PowerShellは喜んで受け入れる文字列"-oC:\scripts\so\new folder"を渡します。7z.exeそれで、7z.exeが次のような両方の形式を受け入れることを知りました

"C:\Program Files\7-zip\7z.exe" e "C:\scripts\so\new folder.zip" -o"C:\scripts\so\new folder"

"C:\Program Files\7-zip\7z.exe" e "C:\scripts\so\new folder.zip" "-oC:\scripts\so\new folder"

また、どちらの例にもスペースが含まれています。

[string]$pathtoexe = "C:\Program Files\7-Zip\7z.exe"
$dir = "C:\scripts\so"
$output = "$dir\new folder"
Get-ChildItem -path $dir -Filter *.zip | % {
    [array]$marguments = "e",$_.FullName,"-o$output";
    & $pathtoexe $marguments
}

PowerShell V3 のもう 1 つのアプローチは、PowerShell の解析機能を回避することです。コマンドを使用して、--%このようなコマンドの解析を停止するように PowerShell に指示できます。

$zipfile = "C:\scripts\so\newfolder.zip"
$destinationfolder = "C:\scripts\so\New Folder"
[string]$pathtoexe = "C:\Program Files\7-Zip\7z.exe"
& $pathtoexe --% e "C:\scripts\so\newfolder.zip" -o"C:\scripts\so\new folder"

この--%構文を使用して、コマンド ラインで入力するのと同じようにコマンドを入力します。このロジックをテストしたところ、ファイルが宛先フォルダーに抽出されました。

の詳細について--%は、 を確認してくださいPS> help about_parsing

このアプローチの問題--%は、変数を含めることができなくなった後です。この問題の解決策は、--%別の文字列変数として を含めて、このように渡すことです。そして、このアプローチは、もともと機能していなかったコマンドライン アプローチに似ています。

[string]$pathtoexe = "C:\Program Files\7-Zip\7z.exe"
$dir = "C:\scripts\so"
$output = "$dir\new folder"

Get-ChildItem -path $dir -Filter *.zip | % {
    $zipfile = $_.FullName;
    [string]$formatted = [System.String]::Concat("e ", """$zipfile"""," -o""$output""");
    [string]$stopparser = '--%';
    & $pathtoexe $stopparser $formatted;
}
于 2013-09-11T16:44:56.107 に答える
3

Windows Sysinternalsスイートの優れたProcess Explorerを使用して、非常に興味深い動作を観察することができました。以下に示すように、コマンドラインを少し簡略化しました。

dir -Path $dir -Filter *.zip |
  select FullName |
  % { & 7za.exe e $_ "-o$dir\tmp" }

これは、Process Explorer によると、実際には次のコマンド ラインを呼び出していました。

C:\temp\7za.exe @{FullName="C:\temp\test.zip"} -oC:\temp\test

プロパティを展開するように PowerShell にFullName指示すると、ハッシュマップから強制的に除外され、7-Zip が処理できる通常の文字列として扱われます。

dir -Path $dir -Filter *.zip |
  select -ExpandProperty FullName |
  % { & 7za.exe e $_ "-o$dir\tmp" }

ファイル名のスペースの処理など、私が実際に考慮または説明していなかった他の問題がまだある可能性がありますが、PowerShell (この場合は v2) がパラメーターを完全に渡していないというメモを追加する価値があると思いました。期待するかもしれません。

于 2013-09-11T22:11:04.940 に答える