I created a couple of scripts that dynamically copy the file names or paths of selected files and folders. One script is for names, the other is for paths.
They work like this:
- If a single file or folder is selected, it will copy the name/path with surrounding double quotes if there is a space anywhere in the name/path, and without surrounding quotes otherwise.
- If multiple files/folders are selected, all of their names/paths will be copied as a list, one per line. Basically like how "Clipboard COPYNAMES" works now, plus some other options below.
Variable Options:
- Customizable Single-Item Quoting (both scripts): If a single file/folder is selected, the
singleItemQuoteMode
variable lets you choose how it will be quoted:- "auto" - Add surrounding quotes only if there are spaces
- "never" - Don't add surrounding quotes even if there are spaces
- "always" - Always add surrounding quotes
- Customizable multi-line quoting (both scripts): If multiple files/folders are selected, the
multiLineQuoteMode
string variable in each script can be set to customize how each line will be quoted. This doesn't affect anything if only one file/folder is selected.- "auto" - Add quotes for lines with spaces in file name
- "never" - Never add quotes when multiple selected
- "always" - Add surrounding quotes to all lines
- Optional terminating character for folders (paths script only): For any folder(s) selected, you can set the
includeTrailingTerminator
string variable to be whatever character you want to appear at the end of the full path.- To include one, for example on Windows it most likely should be a backslash, so you'd do
includeTrailingTerminator = "\\";
(need to escape backslashes so there's two) and it would look likeC:\Path\
instead ofC:\Path
. - To not include one, just set it to an empty string like:
includeTrailingTerminator = "";
- To include one, for example on Windows it most likely should be a backslash, so you'd do
- Optional resolving of symbolic links & junctions (paths script only): The
resolveSymlinks
variable allows you to specify whether to resolve symbolic links and junctions to their target paths when copying paths. This does not apply to shortcuts (.lnk files).- "none" - Do not resolve symbolic links or junctions
- "symlinkedFiles" - Resolve symbolic links for files only
- "symlinkedFolders" - Resolve symbolic links for folders only
- "both" - Resolve symbolic links for both files and folders
Optional Command Arguments For Above Variables:
SINGLE_ITEM_QUOTE_MODE
MULTILINE_QUOTE_MODE
FOLDER_TERMINATOR
(File paths script only)RESOLVE_SYMLINKS
(File paths script only)
Arguments Template (Must put this in the 'Template' box in the command editor to use arguments):
MULTILINE_QUOTE_MODE/O,SINGLE_ITEM_QUOTE_MODE/O,FOLDER_TERMINATOR/O,RESOLVE_SYMLINKS/O
Example - Basic argument usage when calling script as a user command:
-
Copy_File_Names_Auto_Quoted MULTILINE_QUOTE_MODE="never" SINGLE_ITEM_QUOTE_MODE="auto" RESOLVE_SYMLINKS="both"
-
Copy_File_Paths_Auto_Quoted MULTILINE_QUOTE_MODE="never" SINGLE_ITEM_QUOTE_MODE="auto" FOLDER_TERMINATOR="" RESOLVE_SYMLINKS="none"
Example: Using arguments to modify script behavior when certain keys like 'shift' are held down (see documentation about @keydown modifier). Useful if you occasionally want to force it to copy with/without quotes. You'd add the following code to a button for example (assuming you put the script in a user command called "Copy_File_Names_Auto_Quoted"). Same idea would apply using the file path script.
@keydown:none
Copy_File_Names_Auto_Quoted MULTILINE_QUOTE_MODE="never" SINGLE_ITEM_QUOTE_MODE="auto"
@keydown:shift
Copy_File_Names_Auto_Quoted MULTILINE_QUOTE_MODE="never" SINGLE_ITEM_QUOTE_MODE="never"
Here's are the scripts:
Copy_File_Names_Auto_Quoted:
// Copies files or folders names to clipboard with quotes around it if it has spaces. Various optional behavior for multiple selected items
// By ThioJoe
// Updated: 6/13/24
// Discussion Thread / Latest Version: https://resource.dopus.com/t/scripts-to-copy-file-folder-name-s-or-path-s-with-automatic-surrounding-quotes-based-on-spaces/51122
// Updates also available on my GitHub repo: https://github.com/ThioJoe/D-Opus-Scripts
// Arguments Template (Must put this in the 'Template' box in the command editor to use arguments):
// MULTILINE_QUOTE_MODE/O,SINGLE_ITEM_QUOTE_MODE/O
// Example usage of arguments:
// Copy_File_Names_Auto_Quoted MULTILINE_QUOTE_MODE="never" SINGLE_ITEM_QUOTE_MODE="auto"
function OnClick(clickData) {
//------------ Options (Note: If arguments are used when calling the script, these values will be overrided by the arguments) ------------
// multiLineQuoteMode: Affects how quotes are added to each file name when multiple are selected
// Set to 'never' to never add quotes when multiple selected. 'always' to add to all lines. 'auto' to add for lines with spaces in file name
// > Optional Argument Name: MULTILINE_QUOTE_MODE (string value)
var multiLineQuoteMode = "never";
// singleItemQuoteMode: Affects how quotes are added to each file name when a single file/folder is selected
// > Optional Argument Name: SINGLE_ITEM_QUOTE_MODE (string value)
var singleItemQuoteMode = "auto";
//---------------------------------
var tab = clickData.func.sourcetab;
var selectedItems = tab.selected;
if (selectedItems.count == 0) {
return; // No files selected, nothing to do.
}
if (clickData.func.args.got_arg.SINGLE_ITEM_QUOTE_MODE) {
//Validate argument value
argString = clickData.func.args.SINGLE_ITEM_QUOTE_MODE.toLowerCase();
if (argString == "never" || argString == "always" || argString == "auto") {
singleItemQuoteMode = argString;
} else {
singleItemQuoteMode = "auto";
DOpus.Output("ERROR: Invalid SINGLE_ITEM_QUOTE_MODE argument. Must be either 'never', 'always', or 'auto'. Got: " + argString);
}
//DOpus.Output("Received SINGLE_ITEM_QUOTE_MODE argument: " + String(clickData.func.args.SINGLE_ITEM_QUOTE_MODE));
}
if (clickData.func.args.got_arg.MULTILINE_QUOTE_MODE) {
//Validate argument value
argString = clickData.func.args.MULTILINE_QUOTE_MODE.toLowerCase();
if (argString == "never" || argString == "always" || argString == "auto") {
multiLineQuoteMode = argString;
} else {
multiLineQuoteMode = "never";
DOpus.Output("ERROR: Invalid MULTILINE_QUOTE_MODE argument. Must be either 'never', 'always', or 'auto'. Got: " + argString);
}
//DOpus.Output("Received MULTILINE_QUOTE_MODE argument: " + String(clickData.func.args.MULTILINE_QUOTE_MODE));
}
var clipboardText = "";
// If single item is selected
if (selectedItems.count == 1) {
var singleItem = selectedItems(0);
// If no spaces in the filename or option set to not use quotes
if (singleItemQuoteMode != "always" && (singleItem.name.indexOf(" ") == -1 || singleItemQuoteMode == "never")) {
clipboardText = singleItem.name;
} else {
// Filename contains spaces or option set to always use quotes
clipboardText = '"' + singleItem.name + '"';
}
// Multiple files are selected
} else {
for (var i = 0; i < selectedItems.count; i++) {
var fileName = selectedItems(i).name;
//Add a newline character to the beginning starting after the first line
if (i > 0) {
clipboardText += "\n";
}
if (multiLineQuoteMode === "always") {
clipboardText += '"' + fileName + '"';
} else if (multiLineQuoteMode === "auto" && fileName.indexOf(" ") !== -1) {
clipboardText += '"' + fileName + '"';
} else {
clipboardText += fileName;
}
}
}
DOpus.SetClip(clipboardText);
// For debugging:
//DOpus.Output("--- Copied to clipboard: ---\n" + clipboardText);
}
Copy_File_Paths_Auto_Quoted:
// Copies files or folders full paths to clipboard with quotes around it if it has spaces. Various optional behavior for multiple selected items
// By ThioJoe
// Updated: 6/21/24
// Discussion Thread / Latest Version: https://resource.dopus.com/t/scripts-to-copy-file-folder-name-s-or-path-s-with-automatic-surrounding-quotes-based-on-spaces/51122
// Updates also available on my GitHub repo: https://github.com/ThioJoe/D-Opus-Scripts
// Arguments Template (Must put this in the 'Template' box in the command editor to use arguments):
// MULTILINE_QUOTE_MODE/O,SINGLE_ITEM_QUOTE_MODE/O,FOLDER_TERMINATOR/O,RESOLVE_SYMLINKS/O
// Example usage of arguments:
// Copy_File_Paths_Auto_Quoted MULTILINE_QUOTE_MODE="never" SINGLE_ITEM_QUOTE_MODE="auto" FOLDER_TERMINATOR="\" RESOLVE_SYMLINKS="both"
function OnClick(clickData) {
//------------ Options (Note: If arguments are used when calling the script, these values will be overrided by the arguments) ------------
// multiLineQuoteMode: Affects how quotes are added around each file path when multiple are selected
// Set to 'never' to never add quotes when multiple selected. 'always' to add to all lines. 'auto' to add for lines with spaces in file path
// > Optional Argument Name: MULTILINE_QUOTE_MODE (string value)
var multiLineQuoteMode = "never";
// Which trailing path terminator to add (if any) to the end of full paths of folders (basically like the 'noterm' modifier)
// Just set to empty string if none wanted. Don't forget to escape as necessary (to add a backslash would be like: "\\")
// > Optional Argument Name: FOLDER_TERMINATOR (string value)
var includeTrailingTerminator = "";
// singleItemQuoteMode: Affects how quotes are added to each file name when a single file/folder is selected
// > Optional Argument Name: SINGLE_ITEM_QUOTE_MODE (string value)
var singleItemQuoteMode = "auto";
// resolveSymlinksAndJunctions: Whether to copy the resulting linked target path instead of the 'virtual' file/folder for symbolic links (can be either files/folders) and junctions (folders).
// Note: Doesn't apply to shortcuts (.lnk files)
// Possible values: none, symlinkedFiles, symlinkedFolders, both
// > Optional Argument Name: RESOLVE_SYMLINKS (string value)
var resolveSymlinks = "none";
//---------------------------------
var tab = clickData.func.sourcetab;
var selectedItems = tab.selected;
if (selectedItems.count == 0) {
return; // No files selected, nothing to do.
}
if (clickData.func.args.got_arg.SINGLE_ITEM_QUOTE_MODE) {
//Validate argument value
argString = clickData.func.args.SINGLE_ITEM_QUOTE_MODE.toLowerCase();
if (argString == "never" || argString == "always" || argString == "auto") {
singleItemQuoteMode = argString;
} else {
singleItemQuoteMode = "auto";
DOpus.Output("ERROR: Invalid SINGLE_ITEM_QUOTE_MODE argument. Must be either 'never', 'always', or 'auto'. Got: " + argString);
}
//DOpus.Output("Received SINGLE_ITEM_QUOTE_MODE argument: " + String(clickData.func.args.SINGLE_ITEM_QUOTE_MODE));
}
if (clickData.func.args.got_arg.MULTILINE_QUOTE_MODE) {
//Validate argument value
argString = clickData.func.args.MULTILINE_QUOTE_MODE.toLowerCase();
if (argString == "never" || argString == "always" || argString == "auto") {
multiLineQuoteMode = argString;
} else {
multiLineQuoteMode = "never";
DOpus.Output("ERROR: Invalid MULTILINE_QUOTE_MODE argument. Must be either 'never', 'always', or 'auto'. Got: " + argString);
}
//DOpus.Output("Received MULTILINE_QUOTE_MODE argument: " + String(clickData.func.args.MULTILINE_QUOTE_MODE));
}
if (clickData.func.args.got_arg.RESOLVE_SYMLINKS) {
//Validate argument value
argString = clickData.func.args.RESOLVE_SYMLINKS.toLowerCase();
if (argString == "none" || argString == "symlinkedfiles" || argString == "symlinkedfolders" || argString == "both") {
resolveSymlinks = argString;
} else {
resolveSymlinks = "none";
DOpus.Output("ERROR: Invalid RESOLVE_SYMLINKS argument. Must be either 'none', 'symlinkedFiles', 'symlinkedFolders', or 'both'. Got: " + argString);
}
//DOpus.Output("Received RESOLVE_SYMLINKS argument: " + String(clickData.func.args.RESOLVE_SYMLINKS));
}
if (clickData.func.args.got_arg.FOLDER_TERMINATOR) {
includeTrailingTerminator = clickData.func.args.FOLDER_TERMINATOR;
//DOpus.Output("Received FOLDER_TERMINATOR argument");
}
var clipboardText = "";
// If single item is selected
if (selectedItems.count == 1) {
var singleItem = selectedItems(0);
var filePath = String(singleItem.realpath);
// Resolve symlink/junction if needed
if (resolveSymlinks == "both" || (resolveSymlinks == "symlinkedfiles" && !singleItem.is_dir) || (resolveSymlinks == "symlinkedfolders" && singleItem.is_dir)) {
var resolvedPath = DOpus.FSUtil.Resolve(String(singleItem.realpath), "j");
filePath = String(resolvedPath);
}
if (singleItem.is_dir) {
filePath += includeTrailingTerminator;
}
// If no spaces in the file path or option set to not use quotes
if (singleItemQuoteMode != "always" && (filePath.indexOf(" ") == -1 || singleItemQuoteMode == "never")) {
clipboardText = filePath;
} else {
// File path contains spaces or option set to always use quotes
clipboardText = '"' + filePath + '"';
}
} else {
// Multiple items selected
for (var i = 0; i < selectedItems.count; i++) {
var filePath = String(selectedItems(i).realpath);
// Resolve symlink/junction if needed
if (resolveSymlinks == "both" || (resolveSymlinks == "symlinkedfiles" && !selectedItems(i).is_dir) || (resolveSymlinks == "symlinkedfolders" && selectedItems(i).is_dir)) {
var resolvedPath = DOpus.FSUtil.Resolve(String(selectedItems(i).realpath), "j");
filePath = String(resolvedPath);
}
if (selectedItems(i).is_dir) {
filePath += includeTrailingTerminator;
}
//Add a newline character to the beginning starting after the first line
if (i > 0) {
clipboardText += "\n";
}
if (multiLineQuoteMode === "always") {
clipboardText += '"' + filePath + '"';
} else if (multiLineQuoteMode === "auto" && filePath.indexOf(" ") !== -1) {
clipboardText += '"' + filePath + '"';
} else {
clipboardText += filePath;
}
}
}
DOpus.SetClip(clipboardText);
// For debugging:
//DOpus.Output("--- Copied to clipboard: ---\n" + clipboardText);
}