Copy file with square brackets [ ] in the filename

2019-01-24 06:50发布

问题:

I'm using PowerShell on Windows 7, and writing a script to copy a bunch of files from one folder structure to another. Kind of like compiling. The PowerShell Copy-Item cmdlet thinks that square brackets, [ ], are wildcards of some kind, and I am not able to escape them for some reason.

I can't use -LiteralPath, because I want to use an asterisk * wildcard since the filename has a date as part of the filename, and the date changes. The date is used as a version number.

This post was helpful, but no amount of ticks (2x or 4x per bracket) escapes the square brackets.

I am not receiving an error; PowerShell behaves the same as if I entered in the wrong filename.

This is the specific line I'm working on:

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

And this is the whole thing:

# 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"\

What can I do to escape the square brackets and still use a wildcard filename part of the Copy-Item cmdlet?

回答1:

Yes you are right, the double-backtick approach works. But, the problem is that you are using double quotes instead of single quotes to enclose your string. The double-backtick solution seems to only work with single quotes.

So the fixed line of code is:

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

Another good resource on file paths and wired characters etc. is to read this article: Taking Things (Like File Paths) Literally



回答2:

On PowerShell v 2.0 and up the escape character to use is the backslash. For example, if we want to remove the brackets from this string "[Servername: QA01]" which is the sort of output we get from the Exchange Admin PowerShell cmdlet activity in System Center Orchestrator, we use the following logic:

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

This is pretty weird. See, you have to use a single-quote (which normally implies in PowerShell 'evaluate this precisely as written', so this is very odd syntax).

Don't feel bad for not figuring this out on your own, this is very odd syntax.



回答3:

The way that Powershell automatically tab-completes the filename is usually the best way,

Example:

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


回答4:

Apparently, square brackets need double-backticks to escape, which is unusual. Reference here.

You're sure that doesn't work? I've seen it referred to a few times.

Edit: Yes, it works, you used double quotes instead of backticks.

Double quote is above the apostrophe character, next to the Enter key. Backtick is right underneath the Escape key, sharing the key with the tilde, ~.



回答5:

One option is to get the filenames using the legacy dir, which will let you use the * wildcard character, but doesn't try to "blob" the square brackets. Then feed that list to move-item using -literalpath

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


回答6:

There's a difference between ' and `:

  • The first is the single quote that is the non-shift character on the " key.
  • The second is the backtick that I thought I was using but actually wasn't. It's the nonshift character on the ~ key.

This works:

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


回答7:

Assuming nothing else matches, you can use ? instead of the brackets. A file named "a[h-j]", copying to directory "foo":

 copy-item a?h-j? foo