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

时间:2015-11-20 17:17:06

标签: powershell batch-file

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

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

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

1 个答案:

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