I am trying to develop an extension for VSCode and I need to search for the exact file path where my extension is saved. I've tried this code:
var text;
const directoryPath = path.join(Os.homedir(), '.vscode/extensions');
fs.readdir(directoryPath, function (err, files) {
if (err) {
y2.appendLine('Unable to scan directory: ' + err);
}
for (let i=0;i<files.length;i++){
if (files[i].startsWith("MY_EXTENSION")){
text = files[i];
y2.appendLine(text);
break;
}
}
});
y2.appendLine(text);
y2 is only an output channel I added.
The outcome of this code is:
undefined
MY_EXTENSION
If I take out the second y2.appendLine(text) I receive only MY_EXTENSION but I don't get how to make text global or how to modify the value of the global variable text inside readdir.
I also don't understand why it first executes y2.appendLine(text) and then readdir.
It is really important and I would be grateful to have your help!
I'm not sure what exactly you are trying to do there, but looking at your code it seems like you are trying to save some data for your extension in particular.
For this purpose, you probably want to use the globalStorage object instead.
You can learn more about it in the Data storage section and the ExtensionContext documentation.
For the path to your extension, use the context object and its properties:
extensionPath
The absolute file path of the directory containing the extension.
Shorthand notation for ExtensionContext.extensionUri.fsPath
(independent of the uri scheme).
extensionUri
The uri of the directory containing the extension.
From ExtensionContext. If it is just for the purpose of storage, see #mausworks's answer about globalStorage or storagePath, ets.
You could put it in a function like this:
function searchExt() {
const directoryPath = path.join(Os.homedir(), '.vscode/extensions');
fs.readdir(directoryPath, (err, files) => {
let text = null;
if (err) {
y2.appendLine(`Unable to scan directory: ${err}`);
} else {
for (let i = 0; i < files.length; i++) {
if (files[i].startsWith('MY_EXTENSION')) {
text = files[i];
break;
}
}
}
return text;
});
}
const searchResult = searchExt();
Related
I wanted to delete multiple files which are ending with .pdf under the current directory. Suppose I have 3 different pdf files, 1 image file, and one text file, so in these, I want to delete those 3 different pdf files only.
What I have tried.
1st method
fs.unlinkSync('./'+*+pdfname); -> I know this does not make sense
2nd method
try {
var files = (here the list of files should come. However i am failing to get those);
var path="./"
files.forEach(path => fs.existsSync(path) && fs.unlinkSync(path))
} catch (err) {
console.error("not exist")
}
Any different approaches would be appreciated.
Update for the solution:
I have got the solution for my requirement, I just wanted my function to delete all the pdf files and function to be synchronous. However 99% of the solution given by the below author -> https://stackoverflow.com/a/66558251/11781464
fs.readdir is asynchronous and just needs to make it synchronous fs.readdirSync.
below is the updated code and all the credit should go to the author https://stackoverflow.com/a/66558251/11781464.
Updated code
try {
const path = './'
// Read the directory given in `path`
fs.readdirSync(path).forEach((file) => {
// Check if the file is with a PDF extension, remove it
if (file.split('.').pop().toLowerCase() === 'pdf') {
console.log(`Deleting file: ${file}`);
fs.unlinkSync(path + file)
}
});
console.log("Deleted all the pdf files")
return true;
} catch (err) {
console.error("Error in deleting files",err);
}
You can read the directory using fs.readdir and then check for PDF files and delete them. Like this:
fs = require('fs');
try {
path = './'
// Read the directory given in `path`
const files = fs.readdir(path, (err, files) => {
if (err)
throw err;
files.forEach((file) => {
// Check if the file is with a PDF extension, remove it
if (file.split('.').pop().toLowerCase() == 'pdf') {
console.log(`Deleting file: ${file}`);
fs.unlinkSync(path + file)
}
});
});
} catch (err) {
console.error(err);
}
Preliminary Reading
The current working directory of the Node.js process - see update below answer
Path methods
resolve
extName
File System methods
fs.readdirSync
fs.unlinkSync
and classes
dirent
Example
"use strict";
const fs = require('fs');
const path = require('path');
const cwd = process.cwd();
fs.readdirSync( cwd, {withFileTypes: true})
.forEach( dirent => {
if(dirent.isFile()) {
const fileName = dirent.name;
if( path.extname(fileName).toLowerCase() === ".pdf") {
fs.unlinkSync( path.resolve( cwd, fileName));
}
}
});
Notes
untested code
If unlinkSync fails I would assume it returns -1 as per the unlink(2) man page linked in documentation. Personally I would test this using a filename that doesn't exist in cwd.
I believe the {withFileTypes: true} option for readdirSync returns dirent objects with a mime-type value that would allow you to check for files of type application/pdf regardless of extension (not attempted in the example).
Update: path(resolve) adds the current working directory at the beginning of the returned path, when necessary, by default. path.resolve(fileName) will work equally as well as path.resolve(cwd, fileName) in the example.
It seems you know how to delete (unlink) the files - you are asking how to get the file paths?
Try using glob:
const pdfFiles = require("glob").globSync("*.pdf");
Hi here i am attaching tested code for delete all ( only ) .pdf files and not other extension files like .txt , .docs etc from directory.
Note : You can delete any files or directory only from server side.
const fs = require('fs');
const path = require('path')
fs.readdir('../path to directory', (err, files) => {
const pdfFiles = files.filter(el => path.extname(el) === '.pdf')
pdfFiles.forEach(file => {
console.log("Removing File -> ",file);
var filename = "../path to directory/"+file;
fs.unlink(filename,function(err){
if(err) return console.log(err);
console.log('file deleted successfully');
});
});
});
This will gives you a following result in console log.
Removing File -> note.pdf
Removing File -> note2.pdf
file deleted successfully
file deleted successfully
Please feel free to comment any query if have..
i need help writing a node.js application that searches for all sub directories under the current directory which their names contain the specified string.
for example the user want to search all directories that have the string 'test' in it.
what is the js code i need to use?
i try using this:
var walk = function(dir) {
var results = []
var list = fs.readdirSync(dir)
list.forEach(function(file) {
file = dir + '/' + file
var stat = fs.statSync(file)
if (stat && stat.isDirectory()) results = results.concat(walk(file))
else results.push(file)
})
return results
}
Take a look at node-glob
In your case you could use it like this. This pattern will give you all files in the folder that contain at least once test in the name.
var glob = require("glob")
glob("+(test).js", options, function (er, files) {
// files is an array of filenames.
// If the `nonull` option is set, and nothing
// was found, then files is ["**/*.js"]
// er is an error object or null.
if (er) {
// omg something went wrong
throw new Exception(er);
}
var requiredFiles = files.map(function(filename) {
return require(filename);
});
// do something with the required files
});
Following a chat in #amo-editors, I was wondering if the following are possible from a Firefox Addon:
Opening a local XPI for reading
Listing all files in above XPI with their sizes
Reading selected files
Absolutely possible.
1 + 2) Have to use nsIZipReader to read the xpi. This gives you all files within it.
3) To read contents you have to use zip readers getInputStream function and then wrap it in stream instance, then read it with argument of entry.realSize as read on stream takes characters to read.
MDN :: nsIZipWriter
MDN :: nsIZipReader
edit: i was curious. i think i got it. heres example of how to make it dump contents of a zip (list all files within). see the console.log(entryPointer) that spits out the "zip path". it also reads the contents of the files.
var zr = Cc["#mozilla.org/libjar/zip-reader;1"].createInstance(Ci.nsIZipReader);
Cu.import('resource://gre/modules/osfile.jsm');
Cu.import('resource://gre/modules/FileUtils.jsm');
var reusableStreamInstance = Cc['#mozilla.org/scriptableinputstream;1'].createInstance(Ci.nsIScriptableInputStream);
//var pathExtFolder = OS.Path.join(OS.Constants.Path.profileDir, 'extensions');
var pathToXpiToRead = OS.Path.join(OS.Constants.Path.profileDir, 'extensions', 'PortableTester#jetpack.xpi');
var nsiFileXpi = new FileUtils.File(pathToXpiToRead);
//Services.ww.activeWindow.alert(pathToXpiToRead);
try {
zr.open(nsiFileXpi); //if file dne it throws here
var entries = zr.findEntries('*');
while (entries.hasMore()) {
var entryPointer = entries.getNext(); //just a string of "zip path" (this means path to file in zip, and it uses forward slashes remember)
var entry = zr.getEntry(entryPointer); // should return true on `entry instanceof Ci.nsIZipEntry`
console.log('entryPointer', entryPointer);
/* CONSOLE OUTPUT
* "entryPointer" "bootstrap.js" Scratchpad/1:18
*/
console.info('entry', entry);
/* CONSOLE OUTPUT
* "entry" XPCWrappedNative_NoHelper { QueryInterface: QueryInterface(), compression: Getter, size: Getter, realSize: Getter, CRC32: Getter, isDirectory: Getter, lastModifiedTime: Getter, isSynthetic: Getter, permissions: Getter, compression: 8 } Scratchpad/1:19
*/
if (!entry.isDirectory) {
var inputStream = zr.getInputStream(entryPointer);
reusableStreamInstance.init(inputStream);
var fileContents = reusableStreamInstance.read(entry.realSize);
console.log('contenst of file=', fileContents);
} else {
console.log('is directory, no stream to read');
}
}
} catch (ex) {
console.warn('exception occured = ', ex);
if (ex.name == 'NS_ERROR_FILE_NOT_FOUND') {
Services.ww.activeWindow.alert('XPI at path does not exist!\n\nPath = ' + pathToXpiToRead);
}
} finally {
zr.close();
console.log('zr closed');
//Cu.forceGC(); //im not sure shoud i do this here?
}
I'm not sure if I should do a Cu.forceGC() in the finally, maybe #nmaier can advise us on that.
I'm also not sure if I handled reading the input stream properly, it works, but i dont know memory wise. I did .read(entry.realSize) first time doing this.
variable viewer on entry:
How can I use chrome.downloads.onDeterminingFilename to change downloaded file names if the files have extension of JPG or PNG?
I am looking at the example here:
chrome.downloads.onDeterminingFilename.addListener(function(item, __suggest) {
function suggest(filename, conflictAction) {
__suggest({filename: filename,
conflictAction: conflictAction,
conflict_action: conflictAction});
}
var rules = localStorage.rules;
try {
rules = JSON.parse(rules);
} catch (e) {
localStorage.rules = JSON.stringify([]);
}
for (var index = 0; index < rules.length; ++index) {
var rule = rules[index];
if (rule.enabled && matches(rule, item)) {
if (rule.action == 'overwrite') {
suggest(item.filename, 'overwrite');
} else if (rule.action == 'prompt') {
suggest(item.filename, 'prompt');
} else if (rule.action == 'js') {
eval(rule.action_js);
}
break;
}
}
});
This is confusing. How does chrome.downloads.onDeterminingFilename from above detect the name of the file? And once it detects, how did it change the file? Can anyone break down what these codes mean above?
Ref: http://developer.chrome.com/extensions/samples
As soon as the filename is determined onDeterminingFilename event
is triggered upon which a callback function is called and it takes 2
parameters
item object which contains data such as download id, url, filename, referrer etc. (see
https://developer.chrome.com/extensions/downloads#type-DownloadItem)
__suggest which must be called to pass suggestion either synchronously or asynchronously.
A suggest function is defined which will be used to call __suggest
based on the specific rule
All the rules are accessed from the local memory and a for loop runs
to iterate across them.
For each iteration based on the action data in the rule the
suggest function is called with specific filename and
conflictAction.
Basically the filename is aceessed using item.filename and a new filename is suggested by calling __suggest where the value for the key filename contains the new filename.
so I have this method:
module.exports = {
scanDirectory: function() {
walker.on('file', function(root, stat, next) {
files.push(stat.name);
console.log(files[i]);
next();
i++;
//console.log('The number of items in the array is: ' + files.length);
});
return files;
},
readFiles: function(name) {
var text = fs.readFileSync('./views/index.jade', 'utf8');
return text;
}
};
The first part scans the directory and returns the files in the directory. (Assume the first function works) - which it does to a degree when I run the program, but this is just a reference..
For the second function, I would like it to read in the files from the file[i] array instead of specifically specifying
> './views/index.jade'
I was wondering if this is possible...like to clarify, instead of
> readFileSync('./views/blah.txt', 'utf8');...
I want something like...
for(i=0; i<files.length; i++) {
var text = fs.readFileSync(file[i], 'utf8');
return text;
}
If something like this is possible, please guide me how to or point me in the right direction.
Much appreciated, thanks,
Brian
Yes this is definitely possible. If it isn't working than you need to figure out a few things:
What is the value of file[i], does file[i] have the correct permissions, does file[i] exist, what is the value of text.
Somewhere in there you will see something that doesn't quite add up.