繁体   English   中英

重命名文件脚本-如何将当前目录用于上下文菜单

[英]rename files script - how to use current directory for context menu

我有以下脚本,下面的一行拉出上下文/浏览菜单,以便用户轻松导航到他们选择的文件并重命名文件。 而不是使用静态位置作为目录,如何获取启动脚本的当前目录或当前目录?

编辑:我忘了提一提,我也希望能够单独重命名每个文件(提示用户选择文件夹中每个文件),而不是将每个文件重命名为相同的东西。

仅供参考:我使用.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
}

您无需指定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中,它会弹出一个带有消息和“确定”按钮的对话框,在控制台中,它会显示消息和“按任意键继续...”消息,就像您的消息一样。 对于您的脚本,我确定您的工作完美,我只是想分享一下。

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")
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM