Programming
-
It’s just #Vibes Man
-
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:
- Raycast - Download from raycast.com if you haven’t already
- 7zip - Install via Homebrew:
brew install p7zip- 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:
- Copy the folder path
- Trigger the Raycast command
- Paste the path
- 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:
- Select a folder in Finder
- Trigger the Raycast command (I use
Cmd+Shift+7) - 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 fiKey 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.7zalready exists, the script will automatically createproject_v2.7z. If that exists, it’ll createproject_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" fiNo more manual renaming. No more overwriting precious backups.
4. Progress Feedback
Using
@raycast.mode fullOutputmeans 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
- Find your external drive path:
ls /Volumes/Look for your drive name, then determine where you want archives saved. For example:
/Volumes/Expansion/WebProjectsArchive-
Create the script:
- Open Raycast Settings β Extensions β Script Commands
- Click “Create Script Command”
- Paste the script above
- Update the
EXTERNAL_DRIVEvariable with your path - Save it (like
~/Documents/Raycast/Scripts/or~/.local/raycast)
-
Make it executable:
chmod +x ~/.local/raycast/compress-to-external.sh- Assign a hotkey (optional but recommended):
- In Raycast, search for your script
- Press
Cmd+Kand select “Add Hotkey” - I use
Cmd+Shift+7for “Archive”
Using It
Now the workflow is beautifully simple:
- Open Finder
- Select a folder
- Hit your hotkey (or trigger via Raycast search)
- 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_DRIVEmatches exactly. Check with:ls -la /Volumes/YourDrive/YourFolderScript 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.shConclusion
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!
/ DevOps / 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
-
What you should start saying in Standup now
/ DevOps / Programming
-
So the Gemini CLI...
Two minor gripes with the Gemini CLI tool. I know, I know … it just came out.
-
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.
-
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.
-
-
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.
-
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
-
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
-
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. π
-
New release of pkglock-rust
Β
π New release of pkglock-rust crate is out! π
This update brings:
β Unit testing for robust performance.
π Modularized code for better organization and maintainability.
Check out the latest version and give it a try: https://github.com/llbbl/pkglock-rust
pkglock was created to streamline switching between local and remote npm registries, addressing the slowness of npm installations and resolving transpiling issues by being rewritten in Rust.
#rustlangΒ
-
π Mastering Cloud Storage - Smmall Cloud vs. The Giants! π
Just published a new Article!
Dive into my latest blog where I compare cutting-edge cloud storage solutions like Smmall Cloud, Dropshare, CleanShot X, and Google Drive. Discover which service truly stands out in the realm of digital storage efficiency and innovation.
π Key Insights:
Smmall Cloud’s unique features and how it stacks up against established players.
The practicality and cost-effectiveness of each service.
An intriguing peek into building your own cloud storage!
π Exclusive Bonus: Grab a 10% discount on any Smmall.cloud plan inside the article!
Don’t miss out on these vital insights that could transform your approach to digital storage. Click to read and find out which service fits your needs best!
π GitConnected
#CloudStorage #TechBlog #SmmallCloud #DigitalInnovation #StorageSolutions
-
Launching My First Rust Crate: pkglock
Excited to share my first Rust crate: pkglock π
pkglock is a CLI tool that automates the process of switching URLs in your package-lock.json. Tailored to ease the management of local and remote npm registries, it stands out as a handy utility for developers.
Key Features: Configurable: Set up and switch between local and remote URLs effortlessly. Command-Line Support: Execute with various options straight from the command line.
I rewrote it in rust to avoid having to transpile JS in order to support CommonJS and ESM.
-
Introducing pkglock: A Practical npm Utility
Hello Everyone! π Iβm thrilled to say that I published my first npm package: Pkglock. Β
I made it to solve some minor inconveniences that developers might face.
The Problem
While working with npm packages, I found Verdaccio to be quite helpful. Itβs a private npm proxy registry allowing for local caching of npm packages, substantially speeding up the npm installation process. However, the use of Verdaccio introduced a slight hiccup in collaboration. Since it relies on a local cache, the resulting package-lock.json file makes collaboration challenging, as not everyone has access to my private, local cache.
pkglock: A Simple Solution
Enter "pkglock". Itβs a simple tool, nothing flashy, just a practical utility that addresses this issue by making it easier to switch between the public npm registry and a local cached npm registry. Itβs about smoothing out the development workflow, ensuring that you can collaborate with others efficiently despite using a local cache like Verdaccio.
Iβll be writing a more detailed post on Medium soon, delving into the specifics, so keep an eye out for that if youβre interested in learning more.
Until then, Happy Coding! ππ¨βπ»π