diff --git a/docs/src/use/migrate-to-9.0.0.md b/docs/src/use/migrate-to-9.0.0.md
index 4b33690da13..5f57a5d01f7 100644
--- a/docs/src/use/migrate-to-9.0.0.md
+++ b/docs/src/use/migrate-to-9.0.0.md
@@ -30,6 +30,7 @@ The lists below are ordered roughly by the number of users each change is expect
* [Stricter `/* exported */` parsing](#exported-parsing)
* [`"eslint:recommended"` and `"eslint:all"` strings no longer accepted in flat config](#string-config)
* [`varsIgnorePattern` option of `no-unused-vars` no longer applies to catch arguments](#vars-ignore-pattern)
+* [`--output-file` now writes a file to disk even with an empty output](#output-file)
### Breaking changes for plugin developers
@@ -299,6 +300,14 @@ try {
**Related issue(s):** [#17540](https://github.com/eslint/eslint/issues/17540)
+## `--output-file` now writes a file to disk even with an empty output
+
+Prior to ESLint v9.0.0, the `--output-file` flag would skip writing a file to disk if the output was empty. However, in ESLint v9.0.0, `--output-file` now consistently writes a file to disk, even when the output is empty. This update ensures a more consistent and reliable behavior for `--output-file`.
+
+**To address:** Review your usage of the `--output-file` flag, especially if your processes depend on the file's presence or absence based on output content. If necessary, update your scripts or configurations to accommodate this change.
+
+**Related Issues(s):** [#17660](https://github.com/eslint/eslint/issues/17660)
+
## Removed multiple `context` methods
ESLint v9.0.0 removes multiple deprecated methods from the `context` object and moves them onto the `SourceCode` object:
diff --git a/lib/cli.js b/lib/cli.js
index 5100cb17d40..dce15238347 100644
--- a/lib/cli.js
+++ b/lib/cli.js
@@ -285,25 +285,23 @@ async function printResults(engine, results, format, outputFile, resultsMeta) {
const output = await formatter.format(results, resultsMeta);
- if (output) {
- if (outputFile) {
- const filePath = path.resolve(process.cwd(), outputFile);
+ if (outputFile) {
+ const filePath = path.resolve(process.cwd(), outputFile);
- if (await isDirectory(filePath)) {
- log.error("Cannot write to output file path, it is a directory: %s", outputFile);
- return false;
- }
+ if (await isDirectory(filePath)) {
+ log.error("Cannot write to output file path, it is a directory: %s", outputFile);
+ return false;
+ }
- try {
- await mkdir(path.dirname(filePath), { recursive: true });
- await writeFile(filePath, output);
- } catch (ex) {
- log.error("There was a problem writing the output file:\n%s", ex);
- return false;
- }
- } else {
- log.info(output);
+ try {
+ await mkdir(path.dirname(filePath), { recursive: true });
+ await writeFile(filePath, output);
+ } catch (ex) {
+ log.error("There was a problem writing the output file:\n%s", ex);
+ return false;
}
+ } else if (output) {
+ log.info(output);
}
return true;
diff --git a/tests/lib/cli.js b/tests/lib/cli.js
index 04bb8081ae5..212ce82278c 100644
--- a/tests/lib/cli.js
+++ b/tests/lib/cli.js
@@ -1006,6 +1006,19 @@ describe("cli", () => {
assert.isTrue(log.info.notCalled);
});
+ // https://github.com/eslint/eslint/issues/17660
+ it(`should write the file and create dirs if they don't exist even when output is empty with configType:${configType}`, async () => {
+ const filePath = getFixturePath("single-quoted.js");
+ const code = `${flag} --rule 'quotes: [1, single]' --o tests/output/eslint-output.txt ${filePath}`;
+
+ // TODO: fix this test to: await cli.execute(code, null, useFlatConfig);
+ await cli.execute(code, "var a = 'b'", useFlatConfig);
+
+ assert.isTrue(fs.existsSync("tests/output/eslint-output.txt"));
+ assert.strictEqual(fs.readFileSync("tests/output/eslint-output.txt", "utf8"), "");
+ assert.isTrue(log.info.notCalled);
+ });
+
it(`should return an error if the path is a directory with configType:${configType}`, async () => {
const filePath = getFixturePath("single-quoted.js");
const code = `${flag} --rule 'quotes: [1, double]' --o tests/output ${filePath}`;