Files
lucky_shop/scripts/open-directory.js

337 lines
9.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const { exec, spawn } = require('child_process');
const { promisify } = require('util');
const path = require('path');
const fs = require('fs');
const execAsync = promisify(exec);
/**
* 检测当前操作系统
*/
function getOSPlatform() {
const platform = process.platform;
if (platform === 'win32') return 'windows';
if (platform === 'darwin') return 'macos';
if (platform === 'linux') return 'linux';
return 'unknown';
}
/**
* 检查文件或目录是否存在
*/
function checkPathExists(targetPath) {
try {
fs.accessSync(targetPath);
return true;
} catch (error) {
return false;
}
}
/**
* 获取目录路径(如果是文件则返回所在目录)
*/
function getDirectoryPath(targetPath) {
try {
const stats = fs.statSync(targetPath);
if (stats.isFile()) {
return path.dirname(targetPath);
}
if (stats.isDirectory()) {
return targetPath;
}
} catch (error) {
throw new Error(`路径不存在或无法访问: ${targetPath}`);
}
return targetPath;
}
/**
* 在 Windows 系统打开目录
*/
async function openDirectoryWindows(directoryPath) {
// 确保路径使用反斜杠
const normalizedPath = directoryPath.replace(/\//g, '\\');
console.log(`📁 在文件资源管理器中打开: ${normalizedPath}`);
// 方法1: 使用 explorer 命令
try {
const command = `explorer "${normalizedPath}"`;
await execAsync(command);
console.log('✅ 已启动文件资源管理器');
return true;
} catch (error) {
console.warn('方法1失败:', error.message);
}
// 方法2: 使用 start 命令
try {
const command = `start "" "${normalizedPath}"`;
await execAsync(command);
console.log('✅ 已使用 start 命令打开');
return true;
} catch (error) {
console.warn('方法2失败:', error.message);
}
throw new Error('无法在Windows系统中打开目录');
}
/**
* 在 macOS 系统打开目录
*/
async function openDirectoryMacOS(directoryPath) {
console.log(`📁 在访达中打开: ${directoryPath}`);
// 方法1: 使用 open 命令
try {
const command = `open "${directoryPath}"`;
await execAsync(command);
console.log('✅ 已启动访达');
return true;
} catch (error) {
console.warn('方法1失败:', error.message);
}
// 方法2: 使用 open -R 命令(打开包含指定文件的文件夹)
try {
const command = `open -R "${directoryPath}"`;
await execAsync(command);
console.log('✅ 已使用 open -R 命令打开');
return true;
} catch (error) {
console.warn('方法2失败:', error.message);
}
throw new Error('无法在macOS系统中打开目录');
}
/**
* 在 Linux 系统打开目录
*/
async function openDirectoryLinux(directoryPath) {
console.log(`📁 在文件管理器中打开: ${directoryPath}`);
// 尝试不同的文件管理器
const fileManagers = [
'xdg-open', // 标准Linux桌面打开方式
'nautilus', // GNOME
'dolphin', // KDE
'thunar', // XFCE
'pcmanfm', // LXDE
'nemo', // Cinnamon
'caja' // MATE
];
for (const manager of fileManagers) {
try {
// 检查文件管理器是否可用
await execAsync(`which ${manager}`);
const command = `${manager} "${directoryPath}"`;
const child = spawn(manager, [directoryPath], {
stdio: 'ignore',
detached: true
});
child.unref();
console.log(`✅ 已使用 ${manager} 打开目录`);
return true;
} catch (error) {
// 继续尝试下一个文件管理器
continue;
}
}
// 最后尝试 xdg-open最通用的方式
try {
const command = `xdg-open "${directoryPath}"`;
const child = spawn('xdg-open', [directoryPath], {
stdio: 'ignore',
detached: true
});
child.unref();
console.log('✅ 已使用 xdg-open 打开目录');
return true;
} catch (error) {
throw new Error('无法在Linux系统中打开目录请确保已安装文件管理器');
}
}
/**
* 在终端中打开目录(跨平台)
*/
async function openDirectoryInTerminal(directoryPath) {
const os = getOSPlatform();
const dirPath = getDirectoryPath(directoryPath);
console.log(`💻 操作系统: ${os}`);
console.log(`📂 目标目录: ${dirPath}`);
if (!checkPathExists(dirPath)) {
throw new Error(`路径不存在: ${dirPath}`);
}
switch (os) {
case 'windows':
return await openDirectoryWindows(dirPath);
case 'macos':
return await openDirectoryMacOS(dirPath);
case 'linux':
return await openDirectoryLinux(dirPath);
default:
throw new Error(`不支持的操作系统: ${process.platform}`);
}
}
/**
* 在系统默认终端中打开并切换到目录
*/
async function openTerminalInDirectory(directoryPath) {
const os = getOSPlatform();
const dirPath = getDirectoryPath(directoryPath);
console.log(`🖥️ 在终端中打开目录: ${dirPath}`);
if (!checkPathExists(dirPath)) {
throw new Error(`路径不存在: ${dirPath}`);
}
const commands = {
windows: `start cmd /K "cd /d "${dirPath}" && echo 当前目录: %cd%"`,
macos: `osascript -e 'tell application "Terminal" to do script "cd \\\"${dirPath}\\\" && pwd"'`,
linux: `gnome-terminal --working-directory="${dirPath}" || konsole --workdir "${dirPath}" || xterm -e "cd \\"${dirPath}\\" && bash"`
};
try {
let command;
switch (os) {
case 'windows':
command = commands.windows;
break;
case 'macos':
command = commands.macos;
break;
case 'linux':
command = commands.linux;
break;
default:
throw new Error('不支持的操作系统');
}
// 使用 spawn 避免命令注入漏洞
const shell = os === 'windows' ? 'cmd.exe' : '/bin/bash';
const args = os === 'windows' ? ['/c', command] : ['-c', command];
const child = spawn(shell, args, {
stdio: 'ignore',
detached: true
});
child.unref();
console.log('✅ 已启动终端并切换到目录');
return true;
} catch (error) {
console.warn('无法在终端中打开目录:', error.message);
return false;
}
}
/**
* 主函数 - 打开文件所在目录
*/
async function openFileDirectory(filePath, options = {}) {
const {
openInTerminal = false, // 是否在终端中打开
createIfNotExists = false, // 目录不存在时是否创建
wait = false // 是否等待进程结束
} = options;
try {
// 检查路径是否存在
if (!checkPathExists(filePath)) {
if (createIfNotExists) {
const dirPath = path.dirname(filePath);
fs.mkdirSync(dirPath, { recursive: true });
console.log(`📁 创建目录: ${dirPath}`);
} else {
throw new Error(`路径不存在: ${filePath}`);
}
}
const directoryPath = getDirectoryPath(filePath);
if (openInTerminal) {
await openTerminalInDirectory(directoryPath);
} else {
await openDirectoryInTerminal(directoryPath);
}
return true;
} catch (error) {
console.error('❌ 打开目录失败:', error.message);
return false;
}
}
/**
* 使用示例
*/
async function main() {
// 示例1: 打开当前脚本所在目录
const currentFile = __filename;
console.log('当前文件:', currentFile);
// 方法1: 在文件管理器中打开
console.log('\n--- 在文件管理器中打开 ---');
await openFileDirectory(currentFile);
// 等待2秒
await new Promise(resolve => setTimeout(resolve, 2000));
// 方法2: 在终端中打开(可选)
console.log('\n--- 在终端中打开 ---');
await openFileDirectory(currentFile, { openInTerminal: true });
}
// 命令行使用方式
if (require.main === module) {
const args = process.argv.slice(2);
if (args.length === 0) {
// 没有参数,打开当前目录
openFileDirectory(process.cwd())
.then(success => {
if (!success) process.exit(1);
})
.catch(error => {
console.error('错误:', error.message);
process.exit(1);
});
} else {
const filePath = path.resolve(args[0]);
const options = {
openInTerminal: args.includes('--terminal') || args.includes('-t'),
createIfNotExists: args.includes('--create') || args.includes('-c')
};
openFileDirectory(filePath, options)
.then(success => {
if (!success) process.exit(1);
})
.catch(error => {
console.error('错误:', error.message);
process.exit(1);
});
}
}
// 导出函数
module.exports = {
openFileDirectory,
openDirectoryInTerminal,
openTerminalInDirectory,
getOSPlatform
};