Search file based on filename and attach link
Hi, I would like to make a script that search a folder and its subfolder to find a file, based on the filename, that is stored in a specific field of the records (in my case, in the Short title field). When it finds the file, the script attach into the record a link to the file.
I've asked AI to make this script and it returned the following, but it does not work. Someone could help me? Thanks, luca
const { FileUtils } = Components.utils.import("resource://gre/modules/FileUtils.jsm");
(async () => {
const baseFolderPath = "/media/myFolder"; // Update this to your actual folder path
// Use the items passed to the script
const targetItems = items || (item ? [item] : []);
for (let item of targetItems) {
if (!item.isRegularItem()) continue; // Skip non-regular items
if (item.getAttachments().length > 0) continue; // Skip items that already have attachments
const shortTitle = item.getField('shortTitle'); // Get the short title
if (!shortTitle) continue; // Skip if there's no short title
try {
// Call the recursive search function
const filePath = await findFileRecursive(baseFolderPath, shortTitle);
if (filePath) {
await item.linkAttachmentFile(filePath); // Link the found file to the item
Zotero.debug(`Linked file ${filePath} to record ${item.id}`);
} else {
Zotero.debug(`No matching file found for ${shortTitle}`);
}
} catch (e) {
Zotero.debug(`Error searching or linking file for ${shortTitle}: ${e}`);
}
}
})();
// Recursively searches for a file with the given filename in the specified folder and subfolders
async function findFileRecursive(folderPath, filename) {
const folder = new FileUtils.File(folderPath);
const dirEntries = folder.directoryEntries;
while (dirEntries.hasMoreElements()) {
const entry = dirEntries.getNext().QueryInterface(Components.interfaces.nsIFile);
if (entry.isDirectory()) {
const result = await findFileRecursive(entry.path, filename);
if (result) return result; // Return the found file path if found in subdirectory
} else if (entry.isFile() && entry.leafName === filename) {
return entry.path; // Return the path of the matching file
}
}
return null; // Return null if no matching file is found
}
I've asked AI to make this script and it returned the following, but it does not work. Someone could help me? Thanks, luca
const { FileUtils } = Components.utils.import("resource://gre/modules/FileUtils.jsm");
(async () => {
const baseFolderPath = "/media/myFolder"; // Update this to your actual folder path
// Use the items passed to the script
const targetItems = items || (item ? [item] : []);
for (let item of targetItems) {
if (!item.isRegularItem()) continue; // Skip non-regular items
if (item.getAttachments().length > 0) continue; // Skip items that already have attachments
const shortTitle = item.getField('shortTitle'); // Get the short title
if (!shortTitle) continue; // Skip if there's no short title
try {
// Call the recursive search function
const filePath = await findFileRecursive(baseFolderPath, shortTitle);
if (filePath) {
await item.linkAttachmentFile(filePath); // Link the found file to the item
Zotero.debug(`Linked file ${filePath} to record ${item.id}`);
} else {
Zotero.debug(`No matching file found for ${shortTitle}`);
}
} catch (e) {
Zotero.debug(`Error searching or linking file for ${shortTitle}: ${e}`);
}
}
})();
// Recursively searches for a file with the given filename in the specified folder and subfolders
async function findFileRecursive(folderPath, filename) {
const folder = new FileUtils.File(folderPath);
const dirEntries = folder.directoryEntries;
while (dirEntries.hasMoreElements()) {
const entry = dirEntries.getNext().QueryInterface(Components.interfaces.nsIFile);
if (entry.isDirectory()) {
const result = await findFileRecursive(entry.path, filename);
if (result) return result; // Return the found file path if found in subdirectory
} else if (entry.isFile() && entry.leafName === filename) {
return entry.path; // Return the path of the matching file
}
}
return null; // Return null if no matching file is found
}
function findAndLinkPDFs(items) {
if (!items || !items.length) {
Zotero.debug("No items provided");
return;
}
var basePath = "[PATH]";
try {
var directory = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsIFile);
directory.initWithPath(basePath);
if (!directory.exists() || !directory.isDirectory()) {
Zotero.debug("Directory not found or not accessible: " + basePath);
return;
}
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (item.isRegularItem()) {
var shortTitle = item.getField('shortTitle');
if (shortTitle && shortTitle.indexOf('.pdf') > -1) {
searchDirectory(directory, shortTitle.toLowerCase(), item);
}
}
}
Zotero.debug("Search completed");
} catch(e) {
Zotero.debug("Error: " + e);
}
}
function searchDirectory(directory, filename, item) {
try {
if (!directory.exists() || !directory.isDirectory()) {
return false;
}
var entries = directory.directoryEntries;
while (entries.hasMoreElements()) {
var file = entries.getNext().QueryInterface(Components.interfaces.nsIFile);
if (file.exists()) {
if (file.isDirectory()) {
searchDirectory(file, filename, item);
}
else if (file.leafName.toLowerCase() == filename) {
createAttachment(file, item);
return true;
}
}
}
} catch(e) {
Zotero.debug("Error searching directory " + directory.path + ": " + e);
}
return false;
}
function createAttachment(file, item) {
try {
var attachment = new Zotero.Item('attachment');
attachment.parentID = item.id;
attachment.attachmentLinkMode = Zotero.Attachments.LINK_MODE_LINKED_FILE;
attachment.attachmentPath = file.path;
attachment.attachmentContentType = 'application/pdf';
attachment.save();
Zotero.debug("Attached: " + file.leafName);
} catch(e) {
Zotero.debug("Error creating attachment: " + e);
}
}
findAndLinkPDFs(items);