web-dev-qa-db-ja.com

ファイル名に角かっこ[]を含むファイルをコピーし、*ワイルドカードを使用します

私はWindows 7でPowerShellを使用しており、あるフォルダー構造から別のフォルダー構造に一連のファイルをコピーするスクリプトを作成しています。コンパイルのようなもの。 PowerShell Copy-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コマンドレットのワイルドカードファイル名の部分を使用するにはどうすればよいですか?

12

'`には違いがあります:

  • 1つ目は、シングルクォーテーションであり、 " キー。
  • 2つ目は、使用していたと思っていたが実際には使用していなかったバックティックです。それはのシフトなしのキャラクターです ~ キー。

これは機能します:

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

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

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

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

ファイルパスやワイヤードキャラクターなどに関するもう1つの優れたリソースは、この記事を読むことです: (ファイルパスのように)物事を行う


[〜#〜]編集[〜#〜]

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

@ mklement0の優れた答え 、および comments 、および以下の他の答えをさらに詳しく説明します。

単一引用符および2つのバックティックthisの場合; (andbug と不整合を強調する)何が起こっているのかを示すためにいくつかの例を実行してみましょう:

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

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

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

最初に、呼び出されるFile[1]a.txtFile[1]b.txtでテストする2つのファイルを作成しましょう

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

ファイルを取得するさまざまな方法を試します。角括弧[ ]wildcards であることを知っているため、 backtick character でエスケープする必要があります。

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

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

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

単一引用符を使用すると、ワイルドカード文字がある場合、twoバッククォートのセットが必要です。ブラケットをエスケープする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

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


[〜#〜]編集[〜#〜]

@ mklement0の言及 のように、-Pathパラメータを使用したこの動作は一貫性がなく、-Includeパラメータとは異なる動作をします。これは、PowerShellの今後のバージョンで「修正」される可能性があります。


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

19
HAL9256

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

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

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

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

3
FoxDeploy

Powershellが自動的にファイル名をタブ補完する方法が通常は最良の方法です。

例:

copy-item '.\file`[test`].txt'
3
Vasili Syrakis

私はこれを使います:

 Copy-Item  $file.fullname.replace("[", "``[").replace("]", "``]") $DestDir
1
Matteo1010

どうやら、角かっこはエスケープするために二重バックティックを必要としますが、これは珍しいことです。 ここを参照

あなたはそれがうまくいかないと確信していますか?私はそれが数回言及されているのを見ました。

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

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

1
Keeler

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

 cmd /c dir *]* /b |
  foreach { Move-Item -LiteralPath $_ -Destination <destination path>  }
0
mjolinor

他に何も一致しないと仮定すると、?括弧の代わりに。 「a [h-j]」という名前のファイル、ディレクトリ「foo」にコピー:

 copy-item a?h-j? foo 
0
js2010