最近在开发一些小脚本,用 nodejs 实现。其中很多功能需要选择一个/多个文件,或者是选择一个文件夹。
最初的实现是手动输入一个目录(这个只是一个普通的终端文本输入,所以按下 tab 没有路径提示),非常的麻烦,而且很容易输错。
这种情况下网上给出的解决方案都是 electron。但是我一个小脚本用 electron 属实有点夸张了,后来转念一想可以通过 powershell 来实现类似的功能。
对 powershell 不熟悉的我唰的一声打开了 gpt,gpt 不负众望 很快给出了答案
注意这里有区别:cmd 终端中需要调用
powershell.exe
如果当前已经是在 powershell 终端的话,直接运行对应的指令即可
powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $FileDialog = New-Object System.Windows.Forms.OpenFileDialog; $result = $FileDialog.ShowDialog(); if ($result -eq 'OK') { Write-Output $FileDialog.FileName }}"
& {Add-Type -AssemblyName System.Windows.Forms; $FileDialog = New-Object System.Windows.Forms.OpenFileDialog; $result = $FileDialog.ShowDialog(); if ($result -eq 'OK') { Write-Output $FileDialog.FileName }}
运行效果:选择文件后终端会输出你选择的文件的全路径
const { exec, execSync } = require('child_process')
const command = `powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $FileDialog = New-Object System.Windows.Forms.OpenFileDialog; $result = $FileDialog.ShowDialog(); if ($result -eq 'OK') { Write-Output $FileDialog.FileName }}"`
// 异步执行
exec(command, (error, file) => {
console.log(error, file)
})
// 同步执行
const filePath = execSync(command)
console.log('选择的文件', filePath)
到这结束了吗?并没有,我选择的是一个包含中文名称的路径,输入结果如下:
几个小问题:
Buffer
类型
filePath.toString()
获取实际的路径chcp 650
libpng warning: iCCP: cHRM chunk does not match sRGB
调整后执行效果如下:
# 加载 Windows.Forms 程序集
Add-Type -AssemblyName System.Windows.Forms
# 创建 FolderBrowserDialog 对象
$folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog
# 设置对话框的属性
$folderDialog.Description = "请选择文件夹"
$folderDialog.RootFolder = [System.Environment+SpecialFolder]::MyComputer
# 显示文件夹选择对话框
$result = $folderDialog.ShowDialog()
# 检查用户是否点击了 "确定" 按钮
if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
# 输出所选文件夹的路径
Write-Output $folderDialog.SelectedPath
} else {
# 用户取消选择,这里输出空路径
Write-Output ""
}
合并成一行代码则是:
powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog; $folderDialog.Description = '请选择文件夹'; $folderDialog.RootFolder = [System.Environment+SpecialFolder]::MyComputer; $result = $folderDialog.ShowDialog(); if ($result -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $folderDialog.SelectedPath } else { Write-Output '' }}"
多选文件同理:
# 加载 Windows.Forms 程序集
Add-Type -AssemblyName System.Windows.Forms
# 创建 OpenFileDialog 对象
$fileDialog = New-Object System.Windows.Forms.OpenFileDialog
# 设置对话框的属性
$fileDialog.Multiselect = $true
$fileDialog.Title = "请选择文件"
$fileDialog.Filter = "All Files (*.*)|*.*"
# 显示文件选择对话框
$result = $fileDialog.ShowDialog()
# 检查用户是否点击了 "确定" 按钮
if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
# 输出所选文件的路径(数组)
Write-Output $fileDialog.FileNames
} else {
# 用户取消选择
Write-Output ""
}
合并为一行命令:
powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $fileDialog = New-Object System.Windows.Forms.OpenFileDialog; $fileDialog.Multiselect = $true; $fileDialog.Title = '请选择文件'; $fileDialog.Filter = 'All Files (*.*)|*.*'; $result = $fileDialog.ShowDialog(); if ($result -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $fileDialog.FileNames } else { Write-Output '' }}"
filePath.trim()
处理一下多余的字符$fileDialog.Filter = "All Files (*.*)|*.*"
可以用于设置可选择的文件类型的。以下的命令完全来自 GPT,并没有经过测试。自行判断代码是否正常运行 (原谅我并没有 mac)
osascript -e 'POSIX path of (choose file with prompt "请选择一个文件")'
osascript -e 'POSIX path of (choose folder with prompt "请选择一个目录")'
至此,我的小脚本使用体验已经拉满,再也不用一个个输入文件路径了。
总结下所有用到的命令:
Windows
powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $FileDialog = New-Object System.Windows.Forms.OpenFileDialog; $result = $FileDialog.ShowDialog(); if ($result -eq 'OK') { Write-Output $FileDialog.FileName }}"
powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog; $folderDialog.Description = '请选择文件夹'; $folderDialog.RootFolder = [System.Environment+SpecialFolder]::MyComputer; $result = $folderDialog.ShowDialog(); if ($result -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $folderDialog.SelectedPath } else { Write-Output '' }}"
powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $fileDialog = New-Object System.Windows.Forms.OpenFileDialog; $fileDialog.Multiselect = $true; $fileDialog.Title = '请选择文件'; $fileDialog.Filter = 'All Files (*.*)|*.*'; $result = $fileDialog.ShowDialog(); if ($result -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $fileDialog.FileNames } else { Write-Output '' }}"
MacOS
osascript -e 'POSIX path of (choose file with prompt "请选择一个文件")'
osascript -e 'POSIX path of (choose folder with prompt "请选择一个目录")'
略
完 ~