Mqx
Mqx12mo ago

walk() include only last directory...

Hey, I'm currently trying to write a replacer for file names, file content and folder names. My goal is to crawl over a certain directory and then replace a certain pattern in file names, file content and folder names. Currently I use the walk() function from the std library. My problem now is that walk() returns every single directory and not just the last one. In other words, walk() does not just give me:
file/to/directory
file/to/directory
but:
file
file/to
file/to/directory
file
file/to
file/to/directory
What is the best way to filter this? There may also be a better method... This is what my current attempt looks like:
import { parseArgs } from 'https://deno.land/std@0.212.0/cli/mod.ts';
import { walkSync } from 'https://deno.land/std@0.212.0/fs/mod.ts';
import { parseString as parseRegExpString } from 'https://raw.githubusercontent.com/TypeScriptPlayground/std/main/src/regexp/mod.ts'

const args = parseArgs<{
path : string,
pattern : string,
replacer : string
}>(Deno.args);

if (!args.path || !args.pattern || !args.replacer) {
console.log('Missing arguments');
Deno.exit();
}

const pattern = parseRegExpString(args.pattern);

const pathsToUpdate: Array<{ oldPath: string, newPath: string, isFile: boolean }> = [];

Deno.chdir(args.path);
for (const entry of walkSync('.')) {
const path = entry.path;
const pathReplaced = path.replace(pattern, args.replacer);

if (path !== pathReplaced) {
pathsToUpdate.push({ oldPath: path, newPath: pathReplaced, isFile: entry.isFile });
}
}

for (const { oldPath, newPath, isFile } of pathsToUpdate) {
if (isFile) {
const content = Deno.readTextFileSync(oldPath);
const contentReplaced = content.replace(pattern, args.replacer);
Deno.writeTextFileSync(newPath, contentReplaced);
} else {
Deno.renameSync(oldPath, newPath); //<- Error: /path/{{pattern}}/{{pattern}}
}
console.log(`Updated: ${oldPath} -> ${newPath}`);
}
import { parseArgs } from 'https://deno.land/std@0.212.0/cli/mod.ts';
import { walkSync } from 'https://deno.land/std@0.212.0/fs/mod.ts';
import { parseString as parseRegExpString } from 'https://raw.githubusercontent.com/TypeScriptPlayground/std/main/src/regexp/mod.ts'

const args = parseArgs<{
path : string,
pattern : string,
replacer : string
}>(Deno.args);

if (!args.path || !args.pattern || !args.replacer) {
console.log('Missing arguments');
Deno.exit();
}

const pattern = parseRegExpString(args.pattern);

const pathsToUpdate: Array<{ oldPath: string, newPath: string, isFile: boolean }> = [];

Deno.chdir(args.path);
for (const entry of walkSync('.')) {
const path = entry.path;
const pathReplaced = path.replace(pattern, args.replacer);

if (path !== pathReplaced) {
pathsToUpdate.push({ oldPath: path, newPath: pathReplaced, isFile: entry.isFile });
}
}

for (const { oldPath, newPath, isFile } of pathsToUpdate) {
if (isFile) {
const content = Deno.readTextFileSync(oldPath);
const contentReplaced = content.replace(pattern, args.replacer);
Deno.writeTextFileSync(newPath, contentReplaced);
} else {
Deno.renameSync(oldPath, newPath); //<- Error: /path/{{pattern}}/{{pattern}}
}
console.log(`Updated: ${oldPath} -> ${newPath}`);
}
5 Replies
Deno AI Helper
Deno AI Helper12mo ago
The walk() function from the Deno standard library indeed returns every directory and file within the specified directory, recursively. If you want to filter out intermediate directories and only work with the files or the last directory in a path, you'll need to implement a custom filter. One approach to achieve this is to use the entry object that walk() yields. This object contains information about the path, including whether it's a file or a directory. You can use this information to decide whether to process the entry or not. Here's a modified version of your code that filters out intermediate directories: ```ts import { parseArgs } from 'https://deno.land/std@0.212.0/cli/mod.ts'; import { walkSync } from 'https://deno.land/std@0.212.0/fs/mod.ts'; import { parseString as parseRegExpString } from 'https://raw.githubusercontent.com/TypeScriptPlayground/std/main/src/regexp/mod.ts' const args = parseArgs<{ path: string, pattern: string, replacer: string }>(Deno.args); if (!args.path !args.pattern !args.replacer) { console.log('Missing arguments'); Deno.exit(); } const pattern = parseRegExpString(args.pattern); const pathsToUpdate: Array<{ oldPath: string, newPath: string, isFile: boolean }> = []; Deno.chdir(args.path); for (const entry of walkSync('.')) { // Skip intermediate directories if (entry.isDirectory && entry.name !== '.') { continue; } const path = entry.path; const pathReplaced = path.replace(pattern, args.replacer); if (path !== pathReplaced) { pathsToUpdate.push({ oldPath: path, newPath: pathReplaced, isFile: entry.isFile }); } } for (const { oldPath, newPath, isFile } of pathsToUpdate) { if (isFile) { const content = Deno.readTextFileSync(oldPath); const contentReplaced =
Deno AI Helper
Deno AI Helper12mo ago
content.replace(pattern, args.replacer); Deno.writeTextFileSync(newPath, contentReplaced); } else { Deno.renameSync(oldPath, newPath); } console.log(Updated: ${oldPath} -> ${newPath}); } `` In this modified version, we skip over intermediate directories by checking if entry.isDirectory is true and if the entry.name is not '.'. This way, we only process files and the last directory in a given path. Please note that the parseString function from the regexp module is not part of the Deno standard library, and I'm not sure about its behavior or reliability since it's not mentioned in the documentation. Make sure to test this function thoroughly or consider using the native JavaScript RegExp` constructor for parsing regular expressions. Remember to handle errors that may occur during file and
Mqx
MqxOP12mo ago
This throws an error that the path for writeTextFileSync does not exist.
Deno AI Helper
Deno AI Helper12mo ago
The error you're encountering suggests that the new path for writeTextFileSync does not exist. This can happen if you're trying to write to a file in a directory that hasn't been created yet. When you rename files and directories, you need to ensure that the directory structure for the new path exists before you attempt to write to a file or rename a directory. One way to handle this is to check if the directory for the new path exists before writing the file, and if it doesn't, create the necessary directories using Deno.mkdirSync or Deno.mkdir with the recursive option set to true. Here's a snippet that demonstrates how you might do this:
// ... rest of your code ...

for (const { oldPath, newPath, isFile } of pathsToUpdate) {
if (isFile) {
// Ensure the directory for the new file path exists
const newDir = newPath.substring(0, newPath.lastIndexOf('/'));
try {
Deno.statSync(newDir);
} catch (error) {
if (error instanceof Deno.errors.NotFound) {
// Directory does not exist, create it
Deno.mkdirSync(newDir, { recursive: true });
} else {
throw error; // Rethrow unexpected errors
}
}

// Now that we know the directory exists, write the file
const content = Deno.readTextFileSync(oldPath);
const contentReplaced = content.replace(pattern, args.replacer);
Deno.writeTextFileSync(newPath, contentReplaced);
} else {
// For directories, we assume that the parent directory already exists
Deno.renameSync(oldPath, newPath);
}
console.log(`Updated: ${oldPath} -> ${newPath}`);
}

// ... rest of your code ...
// ... rest of your code ...

for (const { oldPath, newPath, isFile } of pathsToUpdate) {
if (isFile) {
// Ensure the directory for the new file path exists
const newDir = newPath.substring(0, newPath.lastIndexOf('/'));
try {
Deno.statSync(newDir);
} catch (error) {
if (error instanceof Deno.errors.NotFound) {
// Directory does not exist, create it
Deno.mkdirSync(newDir, { recursive: true });
} else {
throw error; // Rethrow unexpected errors
}
}

// Now that we know the directory exists, write the file
const content = Deno.readTextFileSync(oldPath);
const contentReplaced = content.replace(pattern, args.replacer);
Deno.writeTextFileSync(newPath, contentReplaced);
} else {
// For directories, we assume that the parent directory already exists
Deno.renameSync(oldPath, newPath);
}
console.log(`Updated: ${oldPath} -> ${newPath}`);
}

// ... rest of your code ...
In this snippet, before writing the file, we check if the directory exists by using Deno.statSync. If it throws a NotFound error, we create the directory
Deno AI Helper
Deno AI Helper12mo ago
with Deno.mkdirSync and the recursive option set to true. This ensures that all the necessary parent directories are created. Please note that this advice is not based on the Deno documentation, and you should double-check the accuracy of the advice given. Make sure to test your code thoroughly to handle any edge cases or errors that might occur.