Zotfile setup - Find all stored (not linked) attachments

Hello! I'm using Zotero with Zotfile to manage my linked attachments, which are stored in a folder that syncs with my OneDrive.

Everything works fine whenever I add an item to Zotero through the journal webpage. However, whenever I add a PDF directly, it gets stored in Zotero storage and does not get automatically moved and renamed by Zotfile. I understand this is expected behaviour.

I can then manually moved them by right clicking an item and choosing "Rename Attachments". That also works. But in the middle of a research session, it's natural that sometimes I miss some (because it opens the pdf in the browser directly), and I get some attachments stored in Zotero Storage while others are in the folder on OneDrive.

Is there any way I can search for "Stored Files" or "Non-linked files" on Zotero so I can periodically go through them and manually run Zotfile on them?
  • Good question. I've been wondering the same kind of thing. :-)
  • Two ways I have used to find stray PDFs that haven't been moved, albeit both external to Zotero:
    (1) Use your OS's file search routine to find any PDFs under the Zotero\Storage hierarchy.
    (2) I use FreeFileSync (Windows app) for backups. It shows me all new files under Zotero\Storage since the last backup. So it's easy to see any new stray PDFs that haven't been moved yet.
  • Thanks, @timwr820. I was thinking of doing something like that. But I've instead decided to go with a saved search based on a system of tags in Zotero that'll let me know whether I've moved a given items attachments or not. Took a few tries to get it working, but it seems like it'll do the trick and help me keep track of things so I'm not looking at the same record multiple times.
  • this would be a very useful feature, seems like it should be possible to set up a search for this but it doesn't seem to be.
    I sometimes end up wanting to make sure a set of items is all on zotero storage (tricky to switch from linked to local, but that's another story), and without this it's necessary just to try moving all of them to be sure, or select one by one.
  • @tmchartrand: You can just select all items and go to Tools → Manage Attachments → Convert Linked Files to Stored Files. Any stored files that are selected will be ignored.
  • Adding to my manual method above for finding locally stored PDFs (that I have omitted to have Zotfile move to my linked storage folder), I now use the code below run in Tools\Developer\Run Javascript. It returns a list of all PDF files that are (still) under the local Zotero\storage folder hierarchy ...

    var sql = "SELECT (? || '\\storage\\' || key || REPLACE(path,'storage:','\\')) AS filepathnames FROM itemAttachments JOIN items USING (itemID) WHERE libraryID=1 AND path IS NOT NULL AND path LIKE ? ORDER BY filepathnames";
    var filepathnames = await Zotero.DB.columnQueryAsync(
    sql,
    [
    Zotero.DataDirectory.dir,
    'storage:%.pdf'
    ]
    );
    return filepathnames.join('\n');
  • @tim820, that's exactly the core of what I've been trying to do. Thanks so much. Is there any way for us that you're aware of to get this JavaScript query output to pull into something like a saved folder?
  • Not sure if I'm understanding exactly what you're asking, but the list on its own may only be a useful starting point for solving file placement problems. It does at least show you the 'size' of your problem.

    Once the list tells you which local PDFs you have omitted to move to your linked folder (Zotfile's Custom Location), you would have to initiate those file moves manually. My javascript/Zotero skills unfortunately aren't up to automating those PDF file moves directly from the list, and then updating Zotero's record of the attached PDF location.

    Doing it manually within Zotero, the first issue is figuring out from each local PDF file path in the list which item the PDF belongs to. But if you had PDF file auto-renaming when the file was stored, that should be easy to tell from the PDF title. Then of course you can move each file individually in Zotero by selecting its item (or Ctrl-click to select more than one at a time), and then selecting Zotfile's Manage Attachments\Rename and Move. Depending on the number of files involved, that could still be a big job. But you probably already knew that !
  • Thanks, @tim820. Finding the individual PDFs seems pretty straightforward on the basis of your search's output since Zotero indexes the file names that are displayed in the search results. So, that's definitely a large step simpler than the process I had been doing. Appreciate your thoughts!
  • @tim820, could you recommend how to modify the query you've suggested above so that it finds *linked* PDFs in a specific drive or directory?

    On my two machines, I have Zotero linking to attachments in a folder on D:\. But for one of these machines, the D:\ path is a symlink to S:\. And apparently I mistakenly on one machine I moved some files and then linked to them as in S:\, so those links are now broken on the machine where I don't have an S:\.

    Thanks so much for any thoughts you may have!
  • @tim820, there was probably a better way to do it, but I realized I could export the itemAttachments table from zotero.sqlite.bak to a CSV and filter the CSV to identify the attachments saved with an S:\ path. :-)
  • edited November 12, 2022
    @dstark glad you sorted out a way to do it. The following code would also get you a list of all linked files (PDFs and others) that Zotero knows about under S:.

    var filepathnames = await Zotero.DB.columnQueryAsync('SELECT path AS filepathnames FROM itemAttachments WHERE path LIKE ? ORDER BY path','S:%');
    return filepathnames.join('\n');

    The list may also include missing attachments - that is attachment files that Zotero thinks are in the linked location folder but are not still there.

    The list will not include 'orphans' - that is, any attachment files in the linked folder location that Zotero no longer has a record of.
  • Thanks so much, @tim820. That'll be very helpful in the event I make this same mistake again. :-)
Sign In or Register to comment.