I would like to run an executable and its path contains an enviroment variable, for example if I would like to run chrome.exe I would like to write something like this
var spawn = require('child_process').spawn;
spawn('chrome',[], {cwd: '%LOCALAPPDATA%\\Google\\Chrome\\Application', env: process.env})
instead of
var spawn = require('child_process').spawn;
spawn('chrome',[], {cwd: 'C:\\Users\myuser\\AppData\\Local\\Google\\Chrome\\Application', env: process.env}).
Is there a package I can use in order to achieve this?
I would like to run an executable and its path contains an enviroment variable, for example if I would like to run chrome.exe I would like to write something like this
var spawn = require('child_process').spawn;
spawn('chrome',[], {cwd: '%LOCALAPPDATA%\\Google\\Chrome\\Application', env: process.env})
instead of
var spawn = require('child_process').spawn;
spawn('chrome',[], {cwd: 'C:\\Users\myuser\\AppData\\Local\\Google\\Chrome\\Application', env: process.env}).
Is there a package I can use in order to achieve this?
Share Improve this question edited Jan 28, 2014 at 17:41 Denys Séguret 382k90 gold badges809 silver badges775 bronze badges asked Jan 26, 2014 at 13:22 Pablo RetykPablo Retyk 5,7506 gold badges46 silver badges59 bronze badges6 Answers
Reset to default 21You can use a regex to replace your variable with the relevant property of process.env
:
let str = '%LOCALAPPDATA%\\Google\\Chrome\\Application'
let replaced = str.replace(/%([^%]+)%/g, (_,n) => process.env[n])
I don't think a package is needed when it's a one-liner.
I realize that the question is asking for Windows environment variables, but I modified @Denys Séguret's answer to handle bash's ${MY_VAR}
and $MY_VAR
style formats as I thought it might be useful for others who came here.
Note: the two arguments are because there are two groupings based on the variations of the format.
str.replace(/\$([A-Z_]+[A-Z0-9_]*)|\${([A-Z0-9_]*)}/ig, (_, a, b) => process.env[a || b])
Here is a generic helper function for this:
/**
* Replaces all environment variables with their actual value.
* Keeps intact non-environment variables using '%'
* @param {string} filePath The input file path with percents
* @return {string} The resolved file path
*/
function resolveWindowsEnvironmentVariables (filePath) {
if (!filePath || typeof(filePath) !== 'string') {
return '';
}
/**
* @param {string} withPercents '%USERNAME%'
* @param {string} withoutPercents 'USERNAME'
* @return {string}
*/
function replaceEnvironmentVariable (withPercents, withoutPercents) {
let found = process.env[withoutPercents];
// 'C:\Users\%USERNAME%\Desktop\%asdf%' => 'C:\Users\bob\Desktop\%asdf%'
return found || withPercents;
}
// 'C:\Users\%USERNAME%\Desktop\%PROCESSOR_ARCHITECTURE%' => 'C:\Users\bob\Desktop\AMD64'
filePath = filePath.replace(/%([^%]+)%/g, replaceEnvironmentVariable);
return filePath;
}
- Can be called from anywhere
- Does basic type checking first, you may want to change what is returned by default in the first
if
block - Functions are named in ways that explain what they do
- Variables are named in ways that explain what they are
- Comments added make it clear what outcomes can occur
- Handles non-environment variables wrapped in percents, since the Windows file system allows for folders to be named
%asdf%
- JSDoc blocks for automated documentation, type checking, and auto-complete in certain editors
- You may also want to use
if (process.platform !== 'win32') {}
depending on your need
These answers are crazy. Just can use path
:
const folder = require('path').join(
process.env.LOCALAPPDATA,
'Google/Chrome/Application',
);
console.log(folder); // C:\Users\MyName\AppData\Local\Google\Chrome\Application
Adding a TypeScript friendly addition to the excellent answer by Denys Séguret:
let replaced = str.replace(/%([^%]+)%/g, (original, matched) => {
const r = Process.env[matched]
return r ? r : ''
})
On Linux/MacOS, I spawn a process to resolve paths with env variables, is safe - let bash to do the work for you. Obviously less performant, but a lot more robust. Looks like this:
import * as cp from 'child_process';
// mapPaths takes an array of paths/strings with env vars, and expands each one
export const mapPaths = (searchRoots: Array<string>, cb: Function) => {
const mappedRoots = searchRoots.map(function (v) {
return `echo "${v}"`;
});
const k = cp.spawn('bash');
k.stdin.end(mappedRoots.join(';'));
const results: Array<string> = [];
k.stderr.pipe(process.stderr);
k.stdout.on('data', (d: string) => {
results.push(d);
});
k.once('error', (e) => {
log.error(e.stack || e);
cb(e);
});
k.once('exit', code => {
const pths = results.map((d) => {
return String(d || '').trim();
})
.filter(Boolean);
cb(code, pths);
});
};