JS Script Rule

Want to use a text file's first line as the filename? Want intelligent categorization by file size? Complex renaming that regular rules can't do - JS scripts can do it all.

This Feature Helps You

  • Use file content as filename: Use the first line of txt/md files as new filename, auto-organize notes
  • Categorize by file size: Add tags like [SMALL], [MEDIUM], [LARGE] to files, see size at a glance
  • Batch rename by config file: Put a rename_rules.txt config file in folder, auto-process by rules
  • JavaScript logic processing: if/else, regex, date calculations - anything you can code, you can do

Quick Start (3 Steps)

  1. Click "Add Rule" button β†’ Select "JS Script"
  2. Pick an example to start: Click "Demo Examples" dropdown, select one close to your needs
  3. Preview first, apply if it looks good

Detailed Examples

Example 1: Force Change Extension

❌ Original: document.txt, report.docx, image.png 😫 Problem: Want to change all file extensions to .zip

βœ… Code:

function main(file_name, file_path, file_index) {
  // Force all files to use .zip extension
  return getFileNameExt(file_name).name + ".zip";
}

βœ… Result: document.zip, report.zip, image.zip

Why this setup: getFileNameExt helps you separate filename and extension, just need simple concatenation. This is the simplest renaming logic.


Example 2: Use Text File First Line as Prefix

❌ Original: note.txt (first line content is "Project Plan") 😫 Problem: Note filenames are too casual, want to use first line content as prefix for easy identification

βœ… Code:

function main(file_name, file_path, file_index) {
  if (file_path == undefined) {
    return file_name;
  }

  const file_data = getFileNameExt(file_name);

  if (file_data.ext === ".txt" || file_data.ext === ".md") {
    try {
      // Read file content
      const content = api.readTextFile(file_path);
      const lines = content.split('\n');
      const firstLine = lines[0] ? lines[0].trim() : '';

      if (firstLine) {
        // Clean illegal characters from filename
        const cleanPrefix = firstLine
          .replace(/[<>:"/\\|?*]/g, '_')
          .substring(0, 20);
        console.log("First line prefix", cleanPrefix);
        return cleanPrefix + "_" + file_name;
      }
    } catch (error) {
      console.log("Failed to read file", error.message);
    }
  }

  return file_name;
}

βœ… Result: Project_Plan_note.txt

Why this setup:

  • First check if file_path exists (may be empty in some cases)
  • Only process .txt and .md files
  • Use try...catch to avoid read failures causing interruption
  • Clean illegal characters, limit prefix length to avoid filename too long

Example 3: Annotate by File Size

❌ Original: photo.jpg (5.2MB) 😫 Problem: Want to know approximate size from filename, convenient for filtering

βœ… Code:

function main(file_name, file_path, file_index) {
  if (file_path == undefined) {
    return file_name;
  }

  const file_data = getFileNameExt(file_name);

  try {
    const fileSizeBytes = api.getFileSize(file_path);
    let sizeCategory = "";
    let sizeLabel = "";

    if (fileSizeBytes < 1024) {
      sizeCategory = "TINY";
      sizeLabel = fileSizeBytes + "B";
    } else if (fileSizeBytes < 1024 * 1024) {
      sizeCategory = "SMALL";
      sizeLabel = Math.round(fileSizeBytes / 1024) + "KB";
    } else if (fileSizeBytes < 1024 * 1024 * 10) {
      sizeCategory = "MEDIUM";
      sizeLabel = Math.round(fileSizeBytes / (1024 * 1024)) + "MB";
    } else {
      sizeCategory = "LARGE";
      sizeLabel = Math.round(fileSizeBytes / (1024 * 1024)) + "MB";
    }

    return `[${sizeCategory}]_${sizeLabel}_${file_data.name}${file_data.ext}`;

  } catch (error) {
    console.log("Failed to get file size", error.message);
    return file_name;
  }
}

βœ… Result: [MEDIUM]_5MB_photo.jpg

Why this setup:

  • Use if/else conditions to classify files into 4 levels
  • Auto-convert units (B/KB/MB) for readability
  • Template strings (backticks) make concatenating multiple variables convenient

Function and API Reference

main Function Signature

All JS scripts must include a main function, this is the program entry point:

function main(file_name, file_path, file_index) {
  // Your renaming logic
  return 'new_name.txt'  // Must return new filename
}

Parameter Description

ParameterTypeDescriptionExample
file_namestringOriginal filename (with extension)"document.txt"
file_pathstring | undefinedAbsolute file path (may be undefined)"/Users/xxx/document.txt"
file_indexnumberFile index (starts from 0)0, 1, 2

Important: file_path may be undefined in some cases (like preview-only mode), must check before using:

if (file_path == undefined) {
  return file_name;
}

Built-in APIs

APIFunctionReturn ValueLimit
api.readTextFile(path)Read text filestringMax 2MB
api.readLines(path)Read file by linesstring[]Max 2MB
api.readBytes(path, offset, length)Read byte rangeUint8ArrayMax 256KB
api.getFileSize(path)Get file size (bytes)number-

Usage Examples:

// Read entire file
const content = api.readTextFile(file_path);

// Read by lines
const lines = api.readLines(file_path);
console.log("First line:", lines[0]);

// Read file header (first 100 bytes)
const header = api.readBytes(file_path, 0, 100);

// Get file size
const size = api.getFileSize(file_path);
console.log("File size:", size, "bytes");

Helper Functions

getFileNameExt(file_name)

Utility function to separate filename and extension:

const result = getFileNameExt("document.txt");
// Returns: { name: "document", ext: ".txt" }

const result2 = getFileNameExt("README");
// Returns: { name: "README", ext: "" }

Return value:

  • name: Filename without extension
  • ext: Extension (with dot prefix like .txt; empty string if no extension)

Platform Feature Differences

Renamio supports two platforms with some functional differences:

uTools Platform

  • βœ… AI code generation: Describe requirements, AI writes code for you
  • βœ… AI fine-tuning: Improve existing code functionality
  • βœ… Use browser console to view console.log output

Tauri Platform

  • βœ… Log window: Independent window displays console.log output, open by toggling "Log Window" switch
  • βœ… Test code: Don't actually rename, only test if code runs normally
  • βœ… More secure sandbox environment

Core functionality is identical: Both platforms have identical main function, built-in APIs, and helper functions.

Built-in Example Details

Click "Demo Examples" dropdown to quickly load 6 built-in examples:

1. Demo: Basic usage

Complete API documentation comments, showing usage of all parameters and built-in functions. Suitable for beginners to understand functionality.

2. Convert extension to .zip

Force change extension to .zip, demonstrates basic usage of getFileNameExt.

3. Delete last 2 characters

Delete last 2 characters from filename, demonstrates boundary checking (keep original name if insufficient characters).

4. Use first line as prefix

Use text file first line as prefix, demonstrates:

  • api.readTextFile to read files
  • File type checking (only process .txt and .md)
  • Illegal character cleaning

5. Annotate with file size

Annotate filename with file size, demonstrates:

  • api.getFileSize to get file size
  • Conditional categorization (TINY/SMALL/MEDIUM/LARGE)
  • Unit conversion and formatted output

6. Rename by config file

Rename based on rename_rules.txt config file in same directory, demonstrates:

  • Reading config file
  • Parsing rule format (pattern->replacement)
  • Wildcard * support
  • Template variable replacement ({name}, {ext}, {index}, {date})

Config file example (rename_rules.txt):

# Comment lines, starting with # will be ignored
*.txt->text_{name}{ext}
*.jpg->photo_{index}{ext}
*->file_{date}_{name}{ext}

Common Questions

❓ Why isn't my code executing?

  1. Check if main function is included Code must contain function main(file_name, file_path, file_index) { ... }

  2. Ensure main function has return Must return new filename, otherwise original name stays unchanged

  3. Check log output

    • Tauri platform: Open "Log Window" switch
    • uTools platform: Open browser developer tools (F12)
  4. Check for syntax errors JavaScript syntax errors will prevent entire script from executing

❓ How to debug code?

Use console.log to output intermediate variables:

function main(file_name, file_path, file_index) {
  console.log("Filename:", file_name);
  console.log("File path:", file_path);
  console.log("File index:", file_index);

  const file_data = getFileNameExt(file_name);
  console.log("Split result:", file_data);

  return file_name;
}

View output:

  • Tauri platform: Toggle "Log Window" switch, opens independent window showing all logs
  • uTools platform: Press F12 to open browser console

Tauri test feature: Click "Test Code" button, runs code with test data (file_name="test.txt", file_index=0), won't actually rename files.

❓ What to do when file reading errors occur?

  1. Check if file_path is undefined

    if (file_path == undefined) {
      console.log("File path is empty, skipping");
      return file_name;
    }
  2. Wrap file read code with try...catch

    try {
      const content = api.readTextFile(file_path);
      // Process content...
    } catch (error) {
      console.log("Read failed:", error.message);
      return file_name;  // Keep original name on failure
    }
  3. Confirm file size is within limits

    • Text reading (readTextFile, readLines): Max 2MB
    • Byte reading (readBytes): Max 256KB
  4. Check if file exists In some cases file path may be invalid, ensure file actually exists

❓ How to handle different file types?

Judge based on extension:

function main(file_name, file_path, file_index) {
  const file_data = getFileNameExt(file_name);

  if (file_data.ext === ".txt" || file_data.ext === ".md") {
    // Handle text files
    return "text_" + file_name;
  } else if (file_data.ext === ".jpg" || file_data.ext === ".png") {
    // Handle image files
    return "image_" + file_name;
  } else {
    // Other files
    return file_name;
  }
}

Notes:

  • ⚠️ File path may be empty: Must check if (file_path == undefined) before using file_path
  • ⚠️ Must handle errors: File reads may fail, use try...catch to avoid interrupting entire process
  • ⚠️ Return value must be string: main function must return new filename, otherwise keeps original name
  • ⚠️ Illegal characters will be filtered: Characters like [\\/:*?"<>|] in filename will be automatically filtered or replaced by system
  • ⚠️ Watch extension case: .jpg and .JPG are different, recommend converting to lowercase for comparison: file_data.ext.toLowerCase() === ".jpg"

Advanced Tips

Combine with Other Rules

  • βœ… Combine with "Sequence": JS script handles complex logic (like reading file content), sequence rule generates uniform numbering
  • βœ… Combine with "Date Rule": JS script reads file metadata, date rule formats timestamps
  • βœ… Combine with "Regex Rule": JS script does complex decisions (like file type categorization), regex rule does text replacement

Use Regular Expressions

JavaScript has built-in regex support:

function main(file_name, file_path, file_index) {
  // Extract numbers from filename
  const match = file_name.match(/\d+/);
  if (match) {
    const number = parseInt(match[0]);
    return `serial${number}_${file_name}`;
  }
  return file_name;
}

Handle Dates and Times

Use JavaScript's Date object:

function main(file_name, file_path, file_index) {
  const now = new Date();
  const dateStr = now.toISOString().slice(0, 10);  // 2024-01-15
  const file_data = getFileNameExt(file_name);
  return `${dateStr}_${file_data.name}${file_data.ext}`;
}

Batch Process Serial Numbers

Use file_index parameter to generate custom serial numbers:

function main(file_name, file_path, file_index) {
  // Start from 1, pad to 3 digits
  const serial = String(file_index + 1).padStart(3, '0');
  const file_data = getFileNameExt(file_name);
  return `${serial}_${file_data.name}${file_data.ext}`;
}

What to Check Out Next?