How to move files found through a query to a specific folder?

Things I have tried

I tried a basic Obsidian query to search for all files in the vault that have a specific tag. I tried right-clicking on these files to move them all together to a specific folder. I figured out this is not possible.

What I’m trying to do

I am trying to move files with a specific tag to specific folders. I don’t know how to do this without moving each file individually. However, this would cost me a lot of time.

1 Like

This might be the simplest approach: Auto-note-mover

But I’m curious about using Dataviewjs + the API (e.g. Vault.rename(file, path)). If I find a moment to try this, I’ll share the results.

1 Like

Here is the second solution.

In the Dataview JS code below you specify a query and a destination folder. It will move files that match the query and have not yet been moved.

In an abundance of caution, first read:

  1. Always backup your vault before performing any sort of batch operation on files. Including this process!
  2. Set the variable ‘moveFiles’ to false until you are REALLY ready to move files. There are several scenarios where this code could execute “prematurely” (e.g. the window is opened in live-preview and you accidentally click-out while editing the Dataview JS code, or you have this file open in another window in ‘reading’ or ‘live-preview’ mode). The code could execute before you are ready and rename or otherwise move unexpected files around. However, you are safe when ‘moveFiles’ is set to false.
  3. The destination folder must end with a path separator (e.g. ‘/’ in 'dest_folder/") otherwise files won’t be moved to where you expect and instead will include part of the path in it’s new name.
  4. To the best of my ability I have tried to make this safe but you are responsible for what happens. I am not liable at all. Period. My vault has years worth of work, and I take precautions not to lose or “misfile” any of it. You should too. Test it first, understand how it works.

Code:

const pathSep = "/"

let moveFiles = false 
let query = "#test_file"
let destination = "destination_folder" + pathSep

if (moveFiles) {
	dv.pages(query)
		.where(page => !page.file.path.startsWith(destination))
		.map(page => this.app.vault.rename(page.file, destination + page.file.name + ".md" ))  
}

dv.table(["Paths"], dv.pages(query).map(page => [page.file.path]))   

Usage:

  1. Recommended but optional: Backup your vault
  2. Set moveFiles to false (to prevent files from being moved until you are ready)
  3. Adjust the query and observe the list of files that would be moved
  4. Set the destination folder and ensure it ends with a path separator (e.g. ‘/’)
  5. For sanity: Double-check the list of files that will be moved
  6. Set moveFiles to true and observe all the files moved to the destination folder. (The script runs when the note is viewed in live-preview or reading mode)

Edge cases:

Q. What if notes have the same name?
A. Only the first note is moved to the destination folder. The other note(s) stay in their original location.

Q. What if the destination folder doesn’t exist?
A. The files are not moved, they stay where they are.

Q. What if I don’t include a path separator (e.g. ‘/’) at the end of the destination folder?
A. The files won’t be moved to that exact folder. Rather the folder above it. And instead the file name will include part of the destination path.

Q. What if I didn’t backup my vault and now my files are in the wrong location or misnamed?
A. Restore your backup. Otherwise, disable the script and manually move and rename files back to where they should be. You were warned. :upside_down_face:

Query documentation: Codeblock Reference - Dataview

Enjoy and good luck!

2 Likes

Very thankful for that! I’ll try in a test vault first, to see if I’ve got the logic of it.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.