Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 85 additions & 1 deletion src/app.js
Original file line number Diff line number Diff line change
@@ -1 +1,85 @@
// write code here
/* eslint-disable no-console */

const fs = require('fs');
const path = require('path');

const args = process.argv.slice(2);

function moveFile(src, dest) {
if (args.length !== 2 || !src || !dest) {
console.error(new Error('Має бути 2 аргумента'));

return;
}

if (args.some((a) => a.startsWith('-'))) {
console.error(new Error('Недійсні аргументи: прапорці заборонені'));

return;
}

const filePath = path.resolve(src);

const fileStats = fs.statSync(filePath, { throwIfNoEntry: false });

if (!fileStats || !fileStats.isFile()) {
console.error(
new Error('Вихідний файл не існує або не є звичайним файлом'),
);

return;
}

let finalDestination = dest;

const destinationExists = fs.existsSync(dest);

if (destinationExists) {
const destinationStats = fs.statSync(dest);

if (destinationStats.isDirectory()) {
finalDestination = path.join(dest, path.basename(src));
} else {
if (dest.endsWith(path.sep) || dest.endsWith('/')) {
console.error(new Error('Призначення не є каталогом'));

return;
}

finalDestination = dest;
}
Comment on lines 42 to 50

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block handles cases where the destination path exists but is not a directory. According to the requirements, a path ending in a / (or \) must be treated as a directory.

Consider what happens if a user runs node index file.txt existing_file/ where existing_file is a file, not a directory. Your code reaches this else block but doesn't differentiate this case. It should produce a specific error, like "destination is not a directory", instead of letting fs.renameSync fail later with a less clear OS-level error.

} else {
const endsWithSlash = dest.endsWith(path.sep);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check for a trailing separator only considers the platform-specific one (path.sep). The requirements state that a path ending in / must be treated as a directory, even on Windows where the native separator is \.

To ensure your script is fully cross-platform, consider updating this line to check for both path.sep and /, similar to the robust check you've already implemented on line 43.


if (endsWithSlash) {
console.error('Каталог призначення не існує');

return;
}

const parentDir = path.dirname(dest);

if (!fs.existsSync(parentDir)) {
console.error('Батьківський каталог призначення не існує');

return;
}

const parentStats = fs.statSync(parentDir, { throwIfNoEntry: false });

if (!parentStats || !parentStats.isDirectory()) {
console.error(new Error('Призначення не є каталогом'));

return;
}
}

try {
fs.renameSync(filePath, finalDestination);
console.log(`File moved successfully to ${finalDestination}`);
} catch (err) {
console.error(err);
}
}

moveFile(args[0], args[1]);