• Automate Folder Archiving on macOS with Raycast and 7zip

    If you’re like me and frequently need to archive project folders to an external drive, you know how tedious the process can be: right-click, compress, wait, find the archive, move it to the external drive, rename if there’s a conflict… It’s a workflow that begs for automation.

    Today, I’m going to show you how I built a custom Raycast script that compresses any folder with 7zip and automatically moves it to an external drive, all with a single keyboard shortcut.

    What We’re Building

    A Raycast script command that:

    • Takes whatever folder you have selected in Finder
    • Compresses it using 7zip (better compression than macOS’s built-in zip)
    • Moves it directly to a specified folder on your external drive
    • Automatically handles version numbering if the archive already exists
    • Provides clear error messages if something goes wrong

    No more manual copying. No more filename conflicts. Just select, trigger, and done.

    Prerequisites

    Before we start, you’ll need:

    1. Raycast - Download from raycast.com if you haven’t already
    2. 7zip - Install via Homebrew:
       brew install p7zip
    
    1. An external drive - Obviously, but make sure you know its mount path

    The Problem with the Built-in Approach

    Initially, I thought: “Can’t I just have Raycast pass the selected folder path as an argument?”

    The answer is technically yes, but it’s clunky. Raycast would prompt you for the folder path every time, which means you’d need to:

    1. Copy the folder path
    2. Trigger the Raycast command
    3. Paste the path
    4. Hit enter

    That’s not automation—that’s just extra steps with good intentions.

    The Solution: AppleScript Integration

    The key insight was using AppleScript to grab the currently selected item from Finder. This way, the workflow becomes:

    1. Select a folder in Finder
    2. Trigger the Raycast command (I use Cmd+Shift+7)
    3. Watch it compress and move automatically

    No input required. No path copying. Just pure automation bliss.

    Building the Script

    Here’s the complete script with all the error handling we need:

    #!/bin/bash
    
    # Required parameters:
    # @raycast.schemaVersion 1
    # @raycast.title Compress Selected to External Drive
    # @raycast.mode fullOutput
    
    # Optional parameters:
    # @raycast.icon 📦
    # @raycast.needsConfirmation false
    
    # Documentation:
    # @raycast.description Compress selected Finder folder with 7zip and move to external drive
    # [@raycast.author](http://raycast.author) Your Name
    
    EXTERNAL_DRIVE="/Volumes/YourDrive/ArchiveFolder"
    
    # Get the selected item from Finder
    FOLDER_PATH=$(osascript -e 'tell application "Finder" to set selectedItems to selection
    if (count of selectedItems) is 0 then
        return ""
    else
        return POSIX path of (item 1 of selectedItems as alias)
    end if')
    
    # Check if anything is selected
    if [ -z "$FOLDER_PATH" ]; then
        echo "❌ Error: No item selected in Finder"
        echo "Please select a folder in Finder and try again"
        exit 1
    fi
    
    # Trim whitespace
    FOLDER_PATH=$(echo "$FOLDER_PATH" | xargs)
    
    # Check if path exists
    if [ ! -e "$FOLDER_PATH" ]; then
        echo "❌ Error: Path does not exist: $FOLDER_PATH"
        exit 1
    fi
    
    # Check if path is a directory
    if [ ! -d "$FOLDER_PATH" ]; then
        echo "❌ Error: Selected item is not a folder: $FOLDER_PATH"
        exit 1
    fi
    
    # Check if 7z is installed
    if ! command -v 7z &> /dev/null; then
        echo "❌ Error: 7z not found. Install with: brew install p7zip"
        exit 1
    fi
    
    # Check if external drive is mounted
    if [ ! -d "$EXTERNAL_DRIVE" ]; then
        echo "❌ Error: External drive not found at: $EXTERNAL_DRIVE"
        echo "Make sure the drive is connected and mounted"
        exit 1
    fi
    
    # Create archive name from folder name
    BASE_NAME="$(basename "$FOLDER_PATH")"
    ARCHIVE_NAME="${BASE_NAME}.7z"
    OUTPUT_PATH="$EXTERNAL_DRIVE/$ARCHIVE_NAME"
    
    # Check if archive already exists and find next available version number
    if [ -f "$OUTPUT_PATH" ]; then
        echo "⚠️  Archive already exists, creating versioned copy..."
        VERSION=2
        while [ -f "$EXTERNAL_DRIVE/${BASE_NAME}_v${VERSION}.7z" ]; do
            VERSION=$((VERSION + 1))
        done
        ARCHIVE_NAME="${BASE_NAME}_v${VERSION}.7z"
        OUTPUT_PATH="$EXTERNAL_DRIVE/$ARCHIVE_NAME"
        echo "📝 Using version number: v${VERSION}"
        echo ""
    fi
    
    echo "🗜️  Compressing: $(basename "$FOLDER_PATH")"
    echo "📍 Destination: $OUTPUT_PATH"
    echo ""
    
    # Compress with 7zip
    if 7z a "$OUTPUT_PATH" "$FOLDER_PATH"; then
        echo ""
        echo "✅ Successfully compressed and moved to external drive"
        echo "📦 Archive: $ARCHIVE_NAME"
        echo "📊 Size: $(du -h "$OUTPUT_PATH" | cut -f1)"
    else
        echo ""
        echo "❌ Error: Compression failed"
        exit 1
    fi
    

    Key Features Explained

    1. Finder Integration

    The AppleScript snippet grabs whatever you have selected in Finder:

    FOLDER_PATH=$(osascript -e 'tell application "Finder" to set selectedItems to selection
    if (count of selectedItems) is 0 then
        return ""
    else
        return POSIX path of (item 1 of selectedItems as alias)
    end if')
    

    This returns a POSIX path (like /Users/yourname/Documents/project) that we can use with standard bash commands.

    2. Comprehensive Error Checking

    The script validates everything before attempting compression:

    • Is anything selected?
    • Does the path exist?
    • Is it actually a directory?
    • Is 7zip installed?
    • Is the external drive connected?

    Each check provides a helpful error message so you know exactly what went wrong.

    3. Automatic Version Numbering

    This was a crucial addition. If project.7z already exists, the script will automatically create project_v2.7z. If that exists, it’ll create project_v3.7z, and so on:

    if [ -f "$OUTPUT_PATH" ]; then
        VERSION=2
        while [ -f "$EXTERNAL_DRIVE/${BASE_NAME}_v${VERSION}.7z" ]; do
            VERSION=$((VERSION + 1))
        done
        ARCHIVE_NAME="${BASE_NAME}_v${VERSION}.7z"
        OUTPUT_PATH="$EXTERNAL_DRIVE/$ARCHIVE_NAME"
    fi
    

    No more manual renaming. No more overwriting precious backups.

    4. Progress Feedback

    Using @raycast.mode fullOutput means you see everything that’s happening:

    • Which folder is being compressed
    • Where it’s going
    • The final archive size

    This transparency is important when you’re archiving large projects that might take a few minutes.

    Setting It Up

    1. Find your external drive path:
       ls /Volumes/
    

    Look for your drive name, then determine where you want archives saved. For example: /Volumes/Expansion/WebProjectsArchive

    1. Create the script:

      • Open Raycast Settings → Extensions → Script Commands
      • Click “Create Script Command”
      • Paste the script above
      • Update the EXTERNAL_DRIVE variable with your path
      • Save it (like ~/Documents/Raycast/Scripts/ or ~/.local/raycast)
    2. Make it executable:

       chmod +x ~/.local/raycast/compress-to-external.sh
    
    1. Assign a hotkey (optional but recommended):
      • In Raycast, search for your script
      • Press Cmd+K and select “Add Hotkey”
      • I use Cmd+Shift+7 for “Archive”

    Using It

    Now the workflow is beautifully simple:

    1. Open Finder
    2. Select a folder
    3. Hit your hotkey (or trigger via Raycast search)
    4. Watch the magic happen

    The script will show you the compression progress and let you know when it’s done, including the final archive size.

    Why 7zip Over Built-in Compression?

    macOS has built-in zip compression, so why bother with 7zip? A few reasons:

    • Better compression ratios - 7zip typically achieves 30-70% better compression than zip
    • Cross-platform - .7z files are widely supported on Windows and Linux
    • More options - If you want to add encryption or split archives later, 7zip supports it
    • Speed - 7zip can be faster for large files

    For project archives that might contain thousands of files and dependencies, these advantages add up quickly.

    Potential Improvements

    This script works great for my needs, but here are some ideas for enhancement:

    • Multiple drive support - Let the user select from available drives
    • Compression level options - Add arguments for maximum vs. fast compression
    • Notification on completion - Use macOS notifications for long-running compressions
    • Delete original option - Add a flag to remove the source folder after successful archiving
    • Batch processing - Handle multiple selected folders

    Troubleshooting

    “7z not found” error:

    brew install p7zip
    

    “External drive not found” error: Make sure your drive is connected and the path in EXTERNAL_DRIVE matches exactly. Check with:

    ls -la /Volumes/YourDrive/YourFolder
    

    Script doesn’t appear in Raycast: Refresh the script directory in Raycast Settings → Extensions → Script Commands → Reload All Scripts

    Permission denied: Make sure the script is executable:

    chmod +x your-script.sh
    

    Conclusion

    This Raycast script has saved me countless hours of manual file management. What used to be a multi-step process involving right-clicks, waiting, dragging, and renaming is now a single keyboard shortcut.

    The beauty of Raycast’s script commands is that they’re just bash scripts with some metadata. If you know bash, you can automate almost anything on your Mac. This particular script demonstrates several useful patterns:

    • Integrating with Finder via AppleScript
    • Robust error handling
    • Automatic file versioning
    • User-friendly progress feedback

    I encourage you to take this script and adapt it to your own workflow. Maybe you want to compress to Dropbox instead of an external drive. Maybe you want to add a timestamp to the filename. The flexibility is there, you just need to modify a few lines.

    Happy automating!


    Have questions or improvements? Feel free to reach out. If you build something cool with this pattern, I’d love to hear about it!

    Tuesday October 14, 2025
  • Programming

    The Password Paradox: When Security Becomes Absurdity

    I created an account on VRBO today and was shocked by their password policy. A password with over 30 characters was flagged as “weak” simply because it didn’t contain special characters. We can do better than this.

    This is the current state of digital security: passwords so complex that humans can’t remember them, pushing us all toward password managers (which, let’s be honest, we should be using). But here’s the thing - while there are some standards and best practices for password security, implementation is wildly inconsistent. Each business decides how much they want to enforce “good” password policies, and even when they try to follow security methodologies, the execution is all over the map.

    You end up with systems that reject genuinely strong passwords while accepting demonstrably weak ones, all because someone’s algorithm prioritizes symbols over entropy.

    It’s security theater at its finest.

    FREE THE EMAILS AT MY blurgl blog

    Monday August 4, 2025
  • What you should start saying in Standup now

    Auto-generated description: A humorous meme depicts a tech status check with All Systems Operational at the top and a detailed performance graph below, highlighting the difference between surface-level responses and actual data.
    Monday August 4, 2025
  • Last Weekend

    🚨 Good Vibes Check! ✅

    Reply with something Positive

    Friday July 4, 2025
  • from the, seat at the table.

    A poetic verse is displayed on a gradient background, featuring the title FIND the ME and imagery of mechanical elements and springs, with an invitation to subscribe at the bottom.A vibrant purple and blue background features a poem titled FIND the ME along with an illustration of a person in a yoga pose and a subscription prompt at the bottom.A poetic text set against a colorful gradient background features a lotus illustration, promoting the blog LLBBL.BLOG with a call to subscribe.
    Friday July 4, 2025
  • Thoughts

    Reply with something Positive

    Wednesday July 2, 2025
  • This just in. Live from Dysmyopia news, Here with updates from the world eye

    Tuesday July 1, 2025
  • Here’s my recently added playlist on Apple Music 👀 music.apple.com/us/playli…

    Monday June 30, 2025
  • (⌐ ͡■ ͜ʖ ͡■), dysmyopia—the dystopian hellscape vision of a world as seen by a short-sighted man.

    Monday June 30, 2025
  • Thoughts

    It could be worse … is WAY BETTER than I can’t decide.

    No wait, never mind … is WAY WORSE than I can’t decide.

    because some days I swap the Better with the Worse,
    and then nothing get’s done.

    I showed up, I gave a shit, For better or worse, Nirvana - Nevermind.

    Monday June 30, 2025
  • Programming

    So the Gemini CLI...

    Two minor gripes with the Gemini CLI tool. I know, I know … it just came out.

    1. There’s no init command to automatically get it to generate its context file. I asked it to do it, and it created an empty file, and then I had to follow up with a second prompt to get it to update the file with helpful information. I’m never going to use that until it’s easier.

    2. I ran a few prompts, and it automatically switched to the flash model, and there’s no way to control what model it uses. Like maybe I’m okay with a bit slower responses if it means I can use the pro-model. I’d like the ability to be able to control this, and there doesn’t seem to be a way to switch between the models.

    Thursday June 26, 2025
  • Thoughts

    Watching Delicious in Dungeon and now I want a Dungeon Taco.

    Wednesday June 25, 2025
  • I built a BlueSky Bot in 6 hours last week. I promise for good reasons.

    TELL THE BOT THEY’RE DOING SUCH A GOOD JOB

    It runs a query, does some analytics, then gives a progress update to socials.

    Wednesday June 25, 2025
  • Productivity

    Threads was perfect cause last year …

    so yea;

    I’m back to blogging. I need to build my own custom Microblog theme, though.

    Go to my Website to see the silly Canva video I made instead of configuring a Debian Server with Ansible using a tool that makes using Docker Swarm more manageable.

    Auto-generated description: A person working on a laptop surrounded by humorous and random digital stickers and text that reads, UGH I, WHEN IT'S TIME TO GET STUFF DONE.

    Wednesday June 25, 2025
  • Programming

    Before: 🔴 47 Dependabot PRs clogging my repo

    After: 🟢 3 meaningful updates per week

    The secret? One .github/dependabot.yml config to ignore patch updates while keeping security fixes.

    Sometimes the best feature is the one that does less work 😌 #Productivity #GitHub #LessIsMore #JavaScript

    Tuesday June 10, 2025
  • Programming

    Claude Code is awesome. Junie is awesome. I want to try Claude Code GitHub Actions but its not included in the Max Plan. What Agents have been working well for you? #javascript #dev #webdev #fullstack

    Tuesday June 10, 2025
  • Programming

    Happy 30th Birthday to PHP! To celebrate, I updated my CodeIgniter project to the latest version, refactored a bunch of stuff. I added a reference implementation of Vue to it. Claude helped. 🎉

    https://github.com/llbbl

    Sunday June 8, 2025
  • The coffee didn’t help #friday #help #sendnaps

    Friday June 6, 2025
  • Thursday June 5, 2025
  • AI

    Bet #GuessThatPrompt

    A silhouetted figure is partially illuminated by a hanging red light bulb, with a prominent blue ring on their hand.A vibrant scene depicts a fantasy setting with oversized whimsical candies surrounding an ornate, bejeweled fantasy object.Two gothic-style figures with eerie appearances stand beside a large, ornate red lightbulb with a blue gemstone at its base, set against a shadowy forest backdrop.A glowing, intricate light bulb is surrounded by mystical, celestial figures and ornate decorations against a starry background.

    Saturday May 17, 2025
  • Really liking Doom: The Dark Ages. The movement and the combat feel very fluid. The shield charge is satisfyingly good. It’s getting great scores on the Reviews.

    Thursday May 15, 2025
  • What are the robots gonna do… when they start keeping a journal? 🤖 Probably complain about their humans. 🤔 #RobotJournal

    Wednesday May 14, 2025
  • I like to live dangerously and listen to that Sleep playlist at work. #TimeToFeed

    Tuesday May 13, 2025
  • I wish I would have prioritized my art more before the Tariffs and bought a Fujifilm X100VI. OH WELL >:(

    Thursday May 8, 2025
  • Gaming

    Anyone playing Elden Ring on Steam Deck??

    I have GeForce Now, two Macs, an Xbox and a Steam Deck. The two games I would play if I had a Gaming Computer: Elden Ring on Steam. Minecraft Bedrock on macOS or GFN. 😮‍💨 Does anyone know if Elden Ring Nightreign will be Crossplay? 😬

    Thursday May 8, 2025