I might be misunderstanding the intended usage of shell-quote, but it seems like strings containing both backslashes and spaces are not handled properly:
Let's consider the string foo \ bar. quote(["foo \\ bar"]) returns 'foo \\ bar', and in bash, echo 'foo \\ bar' prints foo \\ bar.
This failure case does not occur with the same string without spaces (foo\bar): quote(["foo\\bar"]) returns foo\\bar, and in bash, echo foo\\bar prints foo\bar.
Here's a quick typescript file to reproduce with a few test cases:
import { quote } from "shell-quote";
import { spawn } from "child_process";
function spawnCommandWithArgs(
command: string,
args: string[] = [],
): Promise<string> {
return new Promise((resolve, reject) => {
const childProcess = spawn(command, args, {
stdio: "pipe", // Pipe stdout and stderr to parent
});
let stdout = "";
let stderr = "";
// Collect data from stdout
childProcess.stdout.on("data", (data: Buffer) => {
stdout += data.toString();
});
// Collect data from stderr
childProcess.stderr.on("data", (data: Buffer) => {
stderr += data.toString();
});
// Handle command completion
childProcess.on("close", (code) => {
if (code === 0) {
resolve(stdout);
} else {
reject(new Error(stderr || `Command failed with exit code ${code}`));
}
});
// Handle errors starting the process
childProcess.on("error", (err) => {
reject(err);
});
});
}
async function main() {
const testStrings = [
"foo \\ bar",
"foo\\bar",
"foo \\\\ bar",
"foo\\\\bar",
"foo\nbar",
"foo\\\nbar",
];
console.log();
for (const testString of testStrings) {
const quotedWithShellQuote = quote([testString]);
const echoWithShellQuote = await spawnCommandWithArgs("bash", [
"-c",
`echo -n ${quotedWithShellQuote}`,
]);
if (echoWithShellQuote === testString) {
console.log("PASSED:");
} else {
console.log("FAILED:");
}
console.log("*** begin test string");
console.log(testString);
console.log("*** end test string");
if (echoWithShellQuote !== testString) {
console.log("*** begin quoted with shell-quote");
console.log(quotedWithShellQuote);
console.log("*** end quoted with shell-quote");
console.log("*** begin echoed output");
console.log(echoWithShellQuote);
console.log("*** end echoed output");
}
console.log();
}
}
void main()
.then(() => {
process.exit(0);
})
.catch((e) => {
console.error(e);
process.exit(1);
});
The output of running that file is:
FAILED:
*** begin test string
foo \ bar
*** end test string
*** begin quoted with shell-quote
'foo \\ bar'
*** end quoted with shell-quote
*** begin echoed output
foo \\ bar
*** end echoed output
PASSED:
*** begin test string
foo\bar
*** end test string
FAILED:
*** begin test string
foo \\ bar
*** end test string
*** begin quoted with shell-quote
'foo \\\\ bar'
*** end quoted with shell-quote
*** begin echoed output
foo \\\\ bar
*** end echoed output
PASSED:
*** begin test string
foo\\bar
*** end test string
PASSED:
*** begin test string
foo
bar
*** end test string
FAILED:
*** begin test string
foo\
bar
*** end test string
*** begin quoted with shell-quote
'foo\\
bar'
*** end quoted with shell-quote
*** begin echoed output
foo\\
bar
*** end echoed output
I might be misunderstanding the intended usage of shell-quote, but it seems like strings containing both backslashes and spaces are not handled properly:
Let's consider the string
foo \ bar.quote(["foo \\ bar"])returns'foo \\ bar', and in bash,echo 'foo \\ bar'printsfoo \\ bar.This failure case does not occur with the same string without spaces (
foo\bar):quote(["foo\\bar"])returnsfoo\\bar, and in bash,echo foo\\barprintsfoo\bar.Here's a quick typescript file to reproduce with a few test cases:
The output of running that file is: