我在下面的行中有以下脚本,提取上下文/浏览菜单,以便用户轻松导航到他们选择的文件并重命名文件。我没有使用目录的静态位置,而是如何获取启动脚本的当前目录或当前目录?
编辑:我忘了提及我也希望能够单独重命名每个文件(提示用户选择所选文件夹中的每个文件),而不是重命名每个文件。
仅供参考:我使用.bat文件启动此PowerShell脚本。
##########################################################################
#Functions
##########################################################################
# Show input box popup and return the value entered by the user.
function Read-InputBoxDialog([string]$Message, [string]$WindowTitle, [string]$DefaultText)
{
Add-Type -AssemblyName Microsoft.VisualBasic
return [Microsoft.VisualBasic.Interaction]::InputBox($Message, $WindowTitle, $DefaultText)
}
# Show an Open Folder Dialog and return the directory selected by the user.
function Read-FolderBrowserDialog([string]$Message,
[string]$InitialDirectory, [switch]$NoNewFolderButton)
{
$browseForFolderOptions = 0
if ($NoNewFolderButton) { $browseForFolderOptions += 512 }
$app = New-Object -ComObject Shell.Application
$folder = $app.BrowseForFolder(0, $Message, $browseForFolderOptions, $InitialDirectory)
if ($folder) { $selectedDirectory = $folder.Self.Path } else { $selectedDirectory = '' }
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($app) > $null
return $selectedDirectory
}
##########################################################################
#Start Code
##########################################################################
$i = 1
$directoryPath = Read-FolderBrowserDialog -Message "Please select a directory" -NoNewFolderButton -InitialDirectory 'P:\'
if (![string]::IsNullOrEmpty($directoryPath)) { Write-Host "You selected the directory: $directoryPath" }
else { "You did not select a directory." }
$acctdol = Read-InputBoxDialog -Message "Please enter the Account_DOL" -WindowTitle "Account_DateOfLoan" -DefaultText "########_MMDDYYYY_XXX"
if ($acctdol -eq $null) { Write-Host "You clicked Cancel" }
#elseif ($acctdol -eq "Something") { Write-Host "Thanks for typing Something" }
else { Write-Host "You entered $acctdol" }
If(!$acctdol){
$isnull++
}
else{
Get-ChildItem -Path $($directoryPath)*.pdf -Recurse -Force |
ForEach-Object {
$newname = "${acctdol}_{0}.pdf" -f $i
$i++
Rename-Item -Path $_.FullName -NewName $newname
}
}
##########################################################################
#Closing
##########################################################################
if ($Host.Name -eq "ConsoleHost")
{
Write-Host "Press any key to continue..."
$Host.UI.RawUI.FlushInputBuffer() # Make sure buffered input doesn't "press a key" and skip the ReadKey().
$Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp") > $null
}
答案 0 :(得分:3)
您没有指定PS脚本是否与批处理文件位于同一位置,所以我不会认为它是这样,并且将此处理为将脚本的路径硬编码到批处理文件中,并且批处理文件可以在机器上的任何位置。
正如Squashman所指出的,%~dp0
是批处理文件中的当前路径。我要做的是在PS脚本中创建一个接受路径的参数,然后在调用它时将批处理文件的当前路径传递给PS脚本。所以启动脚本就像:
[cmdletBinding()]
Param(
[string]$CallingPath
)
如果您愿意,可以参考BrowseForFolder
来电。在批处理文件中,您可以将其称为:
%windir%\system32\windowspowershell\v1.0\powershell.exe -file c:\Path\To\script.ps1 '%~dp0'
编辑:至于命名每个文件,我猜是给用户提供顺序命名文件或命名每个文件的选项是个好主意,然后如果他们选择为每个文件命名每个文件的一个提示。为了询问他们的偏好,我喜欢Windows.Forms.MessageBox,我有这个功能,我把它放在需要它的脚本的开头:
Function Show-MsgBox ($Text,$Title="",[Windows.Forms.MessageBoxButtons]$Button = "OK",[Windows.Forms.MessageBoxIcon]$Icon="Information"){
[Windows.Forms.MessageBox]::Show("$Text", "$Title", [Windows.Forms.MessageBoxButtons]::$Button, $Icon) | ?{(!($_ -eq "OK"))}
}
然后你可以这样做:
$NameEach = Show-MsgBox -Text "Do you want to rename each file sequentially based on the Account_DOL?`nIf you select No you will be prompted for a name for each file." -Title "Auto-Rename?" -Button YesNo -Icon Question
如果你在ISE中写这个,它会弹出一些选项,供你选择哪些按钮和图标,或者选项卡完整适用于ISE和控制台。
然后,对于命名文件,我会使用Windows.Forms.SaveFileDialog窗口(我喜欢使用Windows.Forms对话框,因为它们对人们很熟悉)。这是一个功能:
Function Get-OutputFilePath{
[CmdletBinding()]
Param(
[String]$Filter = "All Files (*.*)|*.*",
[String]$InitialDirectory,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[Alias('DefaultFileName')]
[String]$FullName,
[Switch]$Force)
BEGIN{
[void][System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
}
PROCESS{
If($FullName -match "\\.+$" -and !$InitialDirectory){$InitialDirectory = Split-Path $FullName;$FullName = Split-Path $FullName -Leaf}ElseIf(!$InitialDirectory){$InitialDirectory=[Environment]::GetFolderPath('Desktop')}
$SaveFileDialog = New-Object System.Windows.Forms.SaveFileDialog
$SaveFileDialog.initialDirectory = $InitialDirectory
Try{$SaveFileDialog.filter = $Filter}Catch{Throw $_;Break}
$SaveFileDialog.FileName = $FullName
$SaveFileDialog.OverwritePrompt = !$Force
If($SaveFileDialog.ShowDialog() -eq "OK"){$SaveFileDialog.FileName}
}
}
看起来比实际情况更糟糕。但是,如果您在函数中包含了这些功能,那么当您在文件中循环重命名时,可以在ForEach
循环中执行此操作:
$newname = If($NameEach -eq 'Yes'){$_|Get-OutputFilePath -Filter 'PDF File (*.pdf)|*.pdf|All Files (*.*)|*.*'|Split-Path -Leaf}Else{"${acctdol}_{0}.pdf" -f $i}
If($_.Name -ne $newname){$_|Rename-Item -NewName $newname}
这将提示他们使用“保存文件”对话框默认为正确的目录,并为当前文件命名,然后将$newname
变量设置为他们选择的任何内容。此外,它做了一些方便的事情,如提示他们是否要覆盖文件,验证文件名和路径,以及类似的东西。我做的最后一件事是确保他们指定了一个新名称,以便我们在尝试将文件重命名为完全相同时不会出错。
奖金功能!我注意到你在脚本的末尾暂停,所以我想传递我用来暂停的功能,因为它在ISE中没有失败,并且允许你传递消息给它显示。在ISE中,它弹出一个带有消息和OK按钮的对话框,在控制台中显示消息和“按任意键继续...”消息,就像你的一样。对于你的剧本我肯定你的作品完美无缺,我只想分享。
Function Invoke-Pause ($Text){
If($psISE){
[Windows.Forms.MessageBox]::Show("$Text", "Script Paused", [Windows.Forms.MessageBoxButtons]"OK", [Windows.Forms.MessageBoxIcon]"Information") | ?{(!($_ -eq "OK"))}
}Else{
Write-Host $Text
Write-Host "Press any key to continue ..."
$Host.UI.RawUI.FlushInputBuffer()
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}
}