19

私は Windows 7 で PowerShell を使用しており、あるフォルダー構造から別のフォルダー構造に一連のファイルをコピーするスクリプトを作成しています。コンパイルのようなもの。PowerShellCopy-Itemコマンドレットは、角かっこ [ ] をある種のワイルドカードと見なし、何らかの理由でそれらをエスケープできません。

-LiteralPathファイル名の一部として日付が含まれており、日付が変更されるため、アスタリスク * ワイルドカードを使用したいので、使用できません。日付はバージョン番号として使用されます。

この投稿は役に立ちましたが、角括弧をエスケープする目盛り (括弧ごとに 2x または 4x) はありません。

エラーは表示されません。PowerShell は、間違ったファイル名を入力した場合と同じように動作します。

これは私が取り組んでいる特定の行です:

#to Fusion Server
Copy-item -Path $FSG\$SW\0.RoomView.Notes\starter\"[RoomView] Versions explained*.pdf" -Destination $FSG\$containerFolder\$rootFolder\"Fusion Server"\

そして、これがすべてです:

# Compiles the Fusion packet for distribution

###############################
###########Variables###########
###############################

#folder structure
$FSG = "F:\FSG"
$containerFolder = "Packet.Fusion for IT and AV Professionals"
$rootFolder      = "Fusion for IT and AV pros $(Get-Date -format “MM-dd-yyyy”)"
$subRoot1        = "Fusion Server"
$subRoot2        = "Scheduling Enhancement and Panels"
$subRoot2sub1    = "Scheduling Panels"
$subRoot3        = "SQL Server"

#source folders
$HW      = "0.Hardware"
$3SMDoc  = "0.Hardware\TPMC-3SM.Documentation"
$4SMDoc  = "0.Hardware\TPMC-4SM.Documentation"
$4SMDDoc = "0.Hardware\TPMC-4SM-FD.Documentation"
$730Doc  = "0.Hardware\TSW-730.Documentation"
$730OLH  = "0.Hardware\TSW-730.OLH"
$CENRVS  = "0.Hardware\CEN-RVS.Notes"

$ProjMgmt = "0.Project Management"

$SW            = "0.Software"
$RVLicensing   = "0.Software\0.RoomView.License"
$RVNotes       = "0.Software\0.RoomView.Notes"
$SQLLicensing  = "0.Software\database.SQL.Licensing"
$SQLNotes      = "0.Software\database.SQL.Notes"
$FRVMarketing  = "0.Software\Fusion RV.Marketing"
$FRVNetworking = "0.Software\Fusion RV.Networking"
$FRVNotes      = "0.Software\Fusion RV.Notes"


###############################
#create the directory structure
###############################

md -Path $FSG\$containerFolder -Name $rootFolder

cd $FSG\$containerFolder\$rootFolder
md "eControl and xPanels"
md "Fusion Server" #$subRoot1
md "Getting Started as a User"
md "Project Management"
md "RoomView Connected Displays"
md "Scheduling Enhancement and Panels" #$subRoot2
md "SQL Server" #$subRoot3

cd $FSG\$containerFolder\$rootFolder\$subRoot1
md "CEN-RVS"
md "Licenseing Information"
md "Networking"
md "Official Documentation"
md "Prerequisites, including powerShell script"
md "Product Info"
md "Requirements"
md "Tech Info"
md "Windows Authentication to Fusion RV"

cd $FSG\$containerFolder\$rootFolder\$subRoot2
md "Outlook Add-in"
md "Scheduling Panels" #$subRoot2sub1

cd $FSG\$containerFolder\$rootFolder\$subRoot2\$subRoot2sub1
md "TPMC-3SM"
md "TPMC-4SM"
md "TPMC-4SM-FD"
md "TSW-730"

cd $FSG\$containerFolder\$rootFolder\$subRoot3
md "Multi-database model only"
md "SQL Licensing"

cd $FSG\$containerFolder
#reset current folder


###############################
#copy the files
###############################

#Copy-Item -Path C:\fso\20110314.log -Destination c:\fsox\mylog.log

#To the root
Copy-item -Path $FSG\$ProjMgmt\starter\"Fusion Support Group Contact info*.pdf" -Destination $FSG\$containerFolder\$rootFolder\
Copy-item -Path $FSG\$containerFolder\"Fusion for IT and AV professionals release notes.txt" -Destination $FSG\$containerFolder\$rootFolder\

#to eControl and xPanels
Copy-item -Path $FSG\$SW\xpanel.Notes\starter\*.* -Destination $FSG\$containerFolder\$rootFolder\"eControl and xPanels"\

#to Fusion Server
Copy-item -Path $FSG\$SW\0.RoomView.Notes\starter\"[RoomView] Versions explained*.pdf" -Destination $FSG\$containerFolder\$rootFolder\"Fusion Server"\

Copy-Item角かっこをエスケープし、コマンドレットのワイルドカード ファイル名部分を引き続き使用するにはどうすればよいですか?

4

9 に答える 9

32

この状況では、括弧をエスケープするために、一重引用符で二重バッククォートを使用する必要があります。二重引用符で囲まれた文字列を使用する場合は、4 つのバッククォートを使用することもできます。

したがって、コードの固定行は次のとおりです。

Copy-item -Path $FSG\$SW\0.RoomView.Notes\starter\'``[RoomView``] Versions explained*.pdf' -Destination $FSG\$containerFolder\$rootFolder\'Fusion Server'\

ファイル パスや有線文字などに関するもう 1 つの優れたリソースは、次の記事を読むことです


編集

この不一致の真の原因は、現在 PowerShell 1にあるバグによるものであることを強調してくれた @mklement0 に感謝します。このバグにより、ワイルドカード文字のエスケープと、デフォルト パラメータのバッククォートが、およびパラメータ-Pathなどの他のパラメータとは異なる動作をします。-Include-Filter

@ mklement0 の優れた回答コメント、および以下のその他の回答を拡張するには:

この状況で一重引用符 2 つのバックティックが必要な理由をよりよく理解するには、次のようにします。(そしてバグと矛盾を強調するために)何が起こっているかを示すためにいくつかの例を見てみましょう:

Get-Item、および関連するコマンドレット ( Get-ChildItemCopy-Itemなど) は、エスケープされたワイルドカード文字エスケープされていないワイルド-Pathカード文字の組み合わせを処理するときに、パラメーターを異なる方法で処理します*同時に***!

TLDR: 一重引用符と二重バッククォートの組み合わせが必要な根本的な理由は、基になる PowerShell プロバイダー-Pathがワイルドカードのパラメーター文字列を解析する方法です。エスケープ文字を 1 回解析し、ワイルドカードを評価するために 2 回解析するようです。

この奇妙な結果を示すために、いくつかの例を見てみましょう。

File[1]a.txtまず、calledと でテストする 2 つのファイルを作成しましょう。File[1]b.txt

"MyFile" | Set-Content '.\File`[1`]a.txt'
"MyFriend" | Set-Content '.\File`[1`]b.txt'

ファイルを取得するためのさまざまな方法を試します。[ ]角括弧がワイルドカードであることはわかっているので、バッククォート文字でエスケープする必要があります。

1 つのファイルを明示的に取得しようとします。

一重引用符で囲まれたリテラル文字列を使用することから始めましょう。

PS C:\> Get-Item 'File[1]a.txt'
PS C:\> Get-Item 'File`[1`]a.txt'

    Directory: C:\

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2019-09-06   5:42 PM              8 File[1]a.txt

PS C:\> Get-Item 'File``[1``]a.txt'

    Directory: C:\

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2019-09-06   5:42 PM              8 File[1]a.txt

一重引用符で囲まれた文字列の場合、ファイルを取得するために必要なバッククォートは 1 つだけですが、バックティックを 2 つ使用することもできます。

二重引用符で囲まれた文字列を使用すると、次のようになります。

PS C:\> Get-Item "File[1]a.txt"
PS C:\> Get-Item "File`[1`]a.txt"
PS C:\> Get-Item "File``[1``]a.txt"

    Directory: C:\  

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2019-09-06   5:42 PM              8 File[1]a.txt

二重引用符で囲まれた文字列の場合、予想どおり、機能させるには 2 つのバッククォートが必要であることがわかります。

ここで、両方のファイルを取得し、ワイルドカードを使用したいと考えています。

一重引用符から始めましょう。

PS C:\> Get-Item 'File[1]*.txt'
PS C:\> Get-Item 'File`[1`]*.txt'
PS C:\> Get-Item 'File``[1``]*.txt'

    Directory: C:\

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2019-09-06   5:42 PM              8 File[1]a.txt
-a----       2019-09-06   5:49 PM             10 File[1]b.txt

一重引用符では、ワイルドカード文字がある場合、2組のバッククォートが必要です。1 つはブラケットをエスケープするためのもので、もう 1 つはワイルドカードが評価されるときにブラケットをエスケープするために使用したバックティックをエスケープするためのものです。

二重引用符についても同様です。

PS C:\> Get-Item "File[1]*.txt"
PS C:\> Get-Item "File`[1`]*.txt"
PS C:\> Get-Item "File``[1``]*.txt"
PS C:\> Get-Item "File```[1```]*.txt"
PS C:\> Get-Item "File````[1````]*.txt"

    Directory: C:\

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2019-09-06   5:42 PM              8 File[1]a.txt
-a----       2019-09-06   5:49 PM             10 File[1]b.txt

二重引用符を使用すると、ワイルドカードで評価するのが少し冗長になります。この場合、4セットのバックティックが必要です。二重引用符の場合、角かっこをエスケープするために 2 つのバッククォートが必要であり、スター ワイルドカードの評価に関しては、エスケープ文字をエスケープするためにさらに 2 つのバッククォートが必要です。


編集

@mklement0 が言及しているように、パラメーターを使用したこの動作-Pathは一貫性が-Includeなく、括弧を適切にエスケープするために 1 つのバッククォートのみが必要なパラメーターとは動作が異なります。これは、PowerShell の新しいバージョンで "修正" される可能性があります。


1 Windows PowerShell v5.1 / PowerShell Core 6.2.0-preview.3 以降

于 2014-01-09T00:49:24.097 に答える
2

どうやら、角括弧をエスケープするには二重のバッククォートが必要ですが、これは珍しいことです。ここを参照してください

あなたはそれがうまくいかないことを確信していますか?何度か言及しているのを見たことがあります。

編集:はい、動作します。バッククォートの代わりに二重引用符を使用しました。

二重引用符は、Enter キーの隣のアポストロフィ文字の上にあります。バックティックは Escape キーのすぐ下にあり、キーをチルダ ~ と共有しています。

于 2014-01-08T22:57:49.223 に答える
2

PowerShell v 2.0 以降では、使用するエスケープ文字はバックスラッシュです。たとえば、System Center Orchestrator の Exchange Admin PowerShell コマンドレット アクティビティから得られる一種の出力であるこの文字列 "[Servername: QA01]" から角かっこを削除する場合は、次のロジックを使用します。

$string -replace '\[','' -replace '\]',''
>Servername: QA01

これはかなり奇妙です。参照してください、単一引用符を使用する必要があります (これは通常、PowerShell で「これを記述どおりに正確に評価する」ことを意味するため、これは非常に奇妙な構文です)。

自分でこれを理解しなくても気にしないでください。これは非常に奇妙な構文です。

于 2015-03-25T15:11:57.367 に答える
0

1 つのオプションは、従来のディレクトリを使用してファイル名を取得することです。これにより、* ワイルドカード文字を使用できますが、角かっこを「ブロブ」しようとしません。次に、-literalpath を使用してそのリストを move-item にフィードします

 cmd /c dir *]* /b |
  foreach { Move-Item -LiteralPath $_ -Destination <destination path>  }
于 2014-01-08T23:06:23.047 に答える