私は Windows 7 で PowerShell を使用しており、あるフォルダー構造から別のフォルダー構造に多数のファイルをコピーするスクリプトを作成しています。コンパイルのようなものです。PowerShellCopy-Item
コマンドレットは、角括弧 [ ] を何らかのワイルドカードであると認識しますが、何らかの理由でエスケープできません。
-LiteralPath
ファイル名の一部に日付が含まれており、日付が変わるため、アスタリスク * ワイルドカードを使用したいのですが、は使用できません。日付はバージョン番号として使用されます。
この郵便受け役に立ちましたが、チェックマークをいくつ付けても(括弧ごとに 2 倍または 4 倍)、角括弧から逃れることはできません。
エラーは表示されません。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
コマンドレットのワイルドカード ファイル名部分を引き続き使用するにはどうすればよいでしょうか?
ベストアンサー1
このような状況では、括弧をエスケープするために、一重引用符とともに二重バックティックを使用する必要があります。二重引用符で囲まれた文字列を使用する場合は、四重バックティックを使用することもできます。
したがって、修正されたコード行は次のようになります。
Copy-item -Path $FSG\$SW\0.RoomView.Notes\starter\'``[RoomView``] Versions explained*.pdf' -Destination $FSG\$containerFolder\$rootFolder\'Fusion Server'\
ファイル パスやワイヤード キャラクタなどに関するもう 1 つの優れたリソースとしては、次の記事があります。物事(ファイルパスなど)を文字通りに受け取る
編集
この矛盾の本当の原因は、PowerShell の現在のバグ1このバグにより、ワイルドカード文字のエスケープや、デフォルト パラメータを使用したバックティックの動作が、他のパラメータ (およびパラメータなど
-Path
) と異なるものになります。-Include
-Filter
さらに詳しく@mklement0 の素晴らしい回答、 そしてコメントその他の回答は以下の通りです。
なぜ必要なのかをよりよく理解するために一重引用符 そして 2つのバックティックでこれ状況; (そしてを強調するバグ矛盾点もありますが、何が起こっているのかを示すために、いくつかの例を見てみましょう。
Get-Item
、および関連するコマンドレット(Get-ChildItem
、Copy-Item
など)は、-Path
組み合わせを扱うときにパラメータを異なる方法で処理します。エスケープされたワイルドカード文字 そして エスケープされていないワイルドカード文字*同時に***!
TLDR: 一重引用符と二重バックティックの組み合わせが必要な根本的な理由は、基盤となる PowerShell プロバイダーが-Path
パラメーター文字列を解析してワイルドカードを検出する方法です。エスケープ文字を検出するために 1 回解析し、ワイルドカードを評価するために 2 回目に解析するようです。
この奇妙な結果を示すために、いくつかの例を見てみましょう。
まず、テスト用の2つのファイルを作成しFile[1]a.txt
、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
シングルクォーテーションでワイルドカード文字を使う場合は、二バックティックのセット。1 つは括弧をエスケープするためのもので、2 つ目のバックティックはワイルドカードが評価されるときに括弧をエスケープするために使用したバックティックをエスケープするためのものです。
二重引用符の場合も同様です。
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
ダブルクォートではワイルドカードで評価すると少し冗長になります。この場合、四バックティックのセット。二重引用符の場合、括弧をエスケープするために 2 つのバックティックが必要であり、アスタリスク ワイルドカードの評価になると、エスケープ文字をエスケープするためにさらに 2 つのバックティックが必要です。
編集
として@mklement0 が言及、この-Path
パラメータの動作は一貫性がなく、-Include
パラメータとは異なる動作をします。パラメータでは、括弧を適切にエスケープするには、バックティックを 1 つだけ使用する必要があります。これは、PowerShell の今後のバージョンで「修正」される可能性があります。
1Windows PowerShell v5.1 / PowerShell Core 6.2.0-preview.3 以降