Hi,
There is another solution posted in this forum using templater but it didn’t work as intended. I think templater is not the right tool for this kind of job anyway. Hence, here is my solution.
Requirement
- Install Obsidian User Plugins
Steps
- Create a script file named
move folder to.js
in the user plugin path you set in the plugin. For instance:MyScripts/UserPlugins
- Add this code into
move folder to.js
module.exports = {};
const { Plugin, Notice, SuggestModal } = require("obsidian");
// Custom SuggestModal for selecting folders.
class FolderSuggester extends SuggestModal {
constructor(app, folders, onChoose) {
super(app);
this.folders = folders;
this.onChoose = onChoose;
this.setPlaceholder("Select a destination folder");
this.titleEl.setText("Move Folder to...");
}
// Filters folders based on user input.
getSuggestions(query) {
return this.folders.filter((folder) =>
folder.path.toLowerCase().includes(query.toLowerCase()),
);
}
// Renders each folder suggestion in the list.
renderSuggestion(folder, el) {
el.createEl("div", { text: folder.path });
}
// Called when a folder is selected.
onChooseSuggestion(folder, evt) {
this.onChoose(folder);
}
}
// Main plugin class.
module.exports.default = class MyPlugin extends Plugin {
async onload() {
// Adds a command to move the current folder.
this.addCommand({
id: "move-current-folder",
name: "Move current file’s folder to another folder",
callback: async () => {
// Gets all loaded files in the vault.
const allFiles = this.app.vault.getAllLoadedFiles();
// Filters only the folders.
const folders = allFiles.filter((file) => {
if (file.path) {
const abstractFile = this.app.vault.getAbstractFileByPath(
file.path,
);
return abstractFile && abstractFile.hasOwnProperty("children"); // Check if the abstractFile has children, indicating it is a folder.
}
return false;
});
// Opens the FolderSuggester to select the destination folder.
new FolderSuggester(this.app, folders, async (selectedFolder) => {
// Gets the current file’s title for debugging
const currentFileTitle = this.app.workspace.getActiveFile().name;
// Gets the path of the current file's parent folder.
const currentFolderPath =
this.app.workspace.getActiveFile().parent.path;
console.log(
`current file path: ${currentFolderPath}/${currentFileTitle}`,
);
if (currentFolderPath === "/") {
// Check if the current folder is the root of the vault.
// Display an error message and exit if it is.
new Notice("Cannot move the root folder.", 3000);
return;
}
// Gets the TFolder object of the current folder.
const currentFolder =
this.app.vault.getAbstractFileByPath(currentFolderPath);
if (currentFolder && selectedFolder) {
// Checks if both the current and selected folders exist.
// Constructs the new path for the folder.
const newFolderPath = `${selectedFolder.path}/${currentFolder.name}`;
// Renames (moves) the folder to the new path.
await this.app.vault.rename(currentFolder, newFolderPath);
// Displays a success notification.
new Notice(
`Successfully moved ${currentFolder.name} to ${selectedFolder.name}`,
2800,
);
}
}).open();
},
});
}
};
- Open the
user plugins
settings and check your script is enabled:
- Open a note and the command palette and type
move folder to
. The command should be in the list as:
Now you can use this command via the palette or add a hotkey.
Enjoy !
P.S.: If you want to convert this script to use it via another plugin, please share below and I will update this post for the people who already use this other plugin instead of user plugins
.