Skip to content

Instantly share code, notes, and snippets.

@yigitkonur
Created November 13, 2025 00:01
Show Gist options
  • Select an option

  • Save yigitkonur/dab41af4a9adb15311271accb5b18084 to your computer and use it in GitHub Desktop.

Select an option

Save yigitkonur/dab41af4a9adb15311271accb5b18084 to your computer and use it in GitHub Desktop.
duti.sh to open all files on sublime
#!/bin/bash
################################################################################
# Comprehensive Sublime Text 4 Default File Association Script
#
# This script sets Sublime Text 4 as the default application for a wide range
# of file extensions commonly used in software development, configuration,
# documentation, and data processing.
#
# Requirements: duti (install via: brew install duti)
# Usage: ./set-sublime-defaults.sh [--dry-run] [--bundle-id <id>]
################################################################################
set -e # Exit on error
# Parse command line arguments
DRY_RUN=false
BUNDLE_ID="com.sublimetext.4"
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run)
DRY_RUN=true
shift
;;
--bundle-id)
BUNDLE_ID="$2"
shift 2
;;
--help)
echo "Usage: $0 [--dry-run] [--bundle-id <id>]"
echo " --dry-run Show what would be done without making changes"
echo " --bundle-id <id> Specify custom bundle ID (default: com.sublimetext.4)"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
# Check if duti is installed
if ! command -v duti &> /dev/null; then
echo "❌ Error: duti is not installed."
echo " Install it with: brew install duti"
exit 1
fi
# Verify Sublime Text is installed
if ! osascript -e "id of app \"Sublime Text\"" &> /dev/null && [ "$DRY_RUN" = false ]; then
echo "⚠️ Warning: Sublime Text might not be installed or not found"
read -p "Continue anyway? (y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
# Enable nullglob to handle empty arrays gracefully
shopt -s nullglob
################################################################################
# EXTENSIONS ARRAY - Organized by Category
################################################################################
EXTENSIONS=(
# ============ PLAIN TEXT & DOCUMENTATION ============
"txt" "text" "rtf" "nfo" "me" "1st"
"readme" "changelog" "authors" "contributors" "license"
"todo" "tasks" "note" "notes"
# ============ MARKDOWN & MARKUP ============
"md" "markdown" "mdown" "mkd" "mkdn" "mdwn" "mdtxt" "rmd" "mdx"
"rst" "rest" "restx" # reStructuredText
"textile"
"asciidoc" "adoc" "asc"
"org" # Org mode
"wiki" "mediawiki"
"creole"
"pod" # Perl documentation
# ============ WEB: HTML & CSS ============
"html" "htm" "xhtml" "shtml" "dhtml" "mhtml"
"css" "scss" "sass" "less" "styl" "stylus"
"postcss"
# ============ WEB: JAVASCRIPT & TYPESCRIPT ============
"js" "mjs" "cjs" "jsx"
"ts" "tsx" "mts" "cts"
"es" "es6" "es7"
"vue" "svelte" "astro"
"coffee" "litcoffee" # CoffeeScript
# ============ WEB: FRAMEWORKS & TEMPLATES ============
"ejs" "eta"
"hbs" "handlebars"
"pug" "jade"
"twig"
"mustache"
"liquid"
"njk" "nunjucks" # Nunjucks
"dust" # Dust.js
"art" # art-template
"dot" "jst" # doT.js
"tmpl" "template"
# ============ WEB: DATA FORMATS ============
"json" "jsonc" "json5" "jsonl" "ndjson"
"xml" "xsl" "xslt" "xsd" "dtd" "rss" "atom"
"svg" "svgz"
"wxml" "wxss" # WeChat Mini Program
# ============ PYTHON ============
"py" "pyw" "pyi" "pyx" "pxd" "pxi" # Python & Cython
"pyc" "pyo" "pyd" # Python compiled
"ipynb" # Jupyter notebooks (JSON based)
"pth" "whl" "egg"
"pip" "pipfile"
"pylintrc" "flake8"
# ============ JAVASCRIPT ECOSYSTEM ============
"npmrc" "yarnrc" "yarnlock" "npmignore"
"nvmrc" "node-version"
"babelrc" "eslintrc" "prettierrc" "stylelintrc"
"jshintrc" "jscsrc" "jsbeautifyrc"
"webpack" "rollup" "vite"
"browserslistrc"
"verdacciorc"
# ============ C/C++ ============
"c" "h" "i"
"cc" "cpp" "cxx" "c++" "cp"
"hh" "hpp" "hxx" "h++" "hp" "hcc"
"ipp" "inl" "inc" "ixx"
"tcc" "tpp"
"def" "map"
# ============ C# & .NET ============
"cs" "csx" "csproj" "cshtml" "aspx" "asax" "ashx" "asmx"
"vb" "vbs" "vbproj" "vbhtml"
"fs" "fsx" "fsi" "fsproj" # F#
"resx" "xaml"
# ============ JAVA & JVM LANGUAGES ============
"java" "jav" "jsp" "jspx"
"class" "jar" "war" "ear"
"kt" "kts" "ktm" # Kotlin
"scala" "sc"
"groovy" "gvy" "gy" "gsh"
"clj" "cljs" "cljc" "edn" "cljx" # Clojure
"gradle" "properties"
"pom" "maven"
# ============ COMPILED LANGUAGES ============
"go" "mod" "sum" "work" # Go
"rs" "rlib" # Rust
"swift" "swiftmodule"
"d" "di" # D
"nim" "nims" "nimble"
"v" "vv" # V
"zig"
"odin"
"carbon"
# ============ FUNCTIONAL LANGUAGES ============
"hs" "lhs" "cabal" # Haskell
"ml" "mli" "mll" "mly" "mlp" # OCaml
"elm"
"purs" # PureScript
"idr" "lidr" # Idris
"agda"
# ============ SCRIPTING LANGUAGES ============
"rb" "rbw" "rake" "gemspec" "ru" "erb" "builder" # Ruby
"pl" "pm" "t" "pod" "al" "cgi" # Perl
"php" "php3" "php4" "php5" "php7" "php8" "phtml" "inc"
"lua" "luau" "wlua"
"tcl" "tk" "wish"
"awk" "gawk" "mawk" "nawk"
"sed"
"m4"
# ============ SHELL SCRIPTING ============
"sh" "bash" "bashrc" "bash_profile" "bash_login" "profile"
"zsh" "zshrc" "zprofile" "zlogin" "zshenv"
"fish"
"ksh" "csh" "tcsh"
"command"
# ============ WINDOWS SCRIPTING ============
"bat" "cmd" "btm"
"ps1" "psm1" "psd1" "ps1xml" "pssc" "psrc" "cdxml"
"vbs" "vbe" "wsf" "wsc"
# ============ R & STATISTICAL ============
"r" "rdata" "rds" "rda"
"rmd" "rnw" "snw" # R Markdown & Sweave
"stan"
# ============ MATLAB & SCIENTIFIC ============
"m" "mat" "fig" # MATLAB
"jl" "jmd" # Julia
"sci" "sce" # Scilab
"nb" "wl" "wls" # Mathematica
"mac" "dem" # Maxima
# ============ FORTRAN & LEGACY ============
"f" "for" "f90" "f95" "f03" "f08"
"cob" "cbl" "cpy" # COBOL
"ada" "adb" "ads" # Ada
"pas" "pp" "inc" # Pascal
# ============ ASSEMBLY ============
"asm" "s" "nasm" "yasm" "fasm" "gas" "a51" "inc" "lst"
# ============ LISPS ============
"lisp" "lsp" "l" "cl" "el" "emacs" "scm" "ss" "rkt" # Lisp variants
# ============ PROLOG & LOGIC ============
"pl" "pro" "prolog" "yap"
# ============ CONFIGURATION FILES ============
"conf" "config" "cfg" "ini" "inf"
"toml" "tml"
"yaml" "yml"
"env" "envrc" "env.local" "env.example"
"editorconfig"
"settings"
"plist" # macOS property list (XML/JSON)
"reg" # Windows registry
"hocon" # HOCON (Human-Optimized Config Object Notation)
# ============ DATA & DATABASES ============
"sql" "mysql" "pgsql" "psql" "plsql" "ddl" "dml"
"sqlite" "sqlite3" "db" "db3"
"csv" "tsv" "dsv" "psv"
"dat" "data"
"cql" "cypher" # Cassandra & Neo4j
"hql" # Hive
"pig" # Pig Latin
"graphql" "gql" "graphqls"
# ============ INFRASTRUCTURE AS CODE ============
"tf" "tfvars" "tfstate" # Terraform
"hcl" "nomad" "sentinel" # HashiCorp
"pp" # Puppet
"sls" # Salt Stack
"cfn" "template" # CloudFormation
"bicep" # Azure Bicep
"pkr" # Packer
"vagrantfile" "vagrant"
# ============ ANSIBLE & AUTOMATION ============
"ansible" "inventory" "hosts"
"j2" "jinja" "jinja2"
"j2.yaml" "j2.yml" "j2.json" "j2.xml"
# ============ DOCKER & CONTAINERS ============
"dockerfile" "containerfile"
"dockerignore" "dockercompose"
"compose"
# ============ KUBERNETES ============
"k8s" "kube"
"kubeconfig"
"helm" "helmignore"
# ============ CI/CD ============
"jenkinsfile" "jenkins"
"gitlab-ci" "travis"
"circleci" "appveyor"
"azure-pipelines" "buildspec"
"wercker" "drone"
"gocd"
# ============ VERSION CONTROL ============
"gitignore" "gitattributes" "gitmodules" "gitconfig" "gitkeep"
"gitinclude" "mailmap"
"hgignore" "hgrc" # Mercurial
"svnignore"
"cvsignore"
"bzrignore" # Bazaar
# ============ BUILD SYSTEMS ============
"makefile" "make" "mk" "mak" "gmk"
"cmake" "cmakecache" "cmakeliststxt"
"ninja" "gn" "gyp"
"scons" "sconstruct" "sconscript"
"bazel" "bzl" "build" "workspace"
"buck" "buckconfig"
"meson" "mesonbuild"
"rakefile" "rake"
"ant" "build.xml"
"sbt"
# ============ PACKAGE MANAGERS ============
"gemfile" "gemfile.lock" "podfile" "podspec" # Ruby
"package" "package-lock" "shrinkwrap" # npm
"cargo" "cargo.lock" # Rust
"go.mod" "go.sum" # Go
"mix" "mix.exs" "mix.lock" # Elixir
"pubspec" "pubspec.lock" # Dart
"requirements" "requirements.txt" "constraints.txt" # Python
"poetry" "poetry.lock" "pyproject" # Python Poetry
"cabal" "stack" "package.yaml" # Haskell
"shard" "shard.lock" # Crystal
"dub" "dub.json" # D
# ============ SHADER LANGUAGES ============
"glsl" "vert" "frag" "geom" "tesc" "tese" "comp"
"hlsl" "fx" "fxh" "cg" "cgfx"
"metal"
"wgsl"
"shader"
# ============ GAME DEVELOPMENT ============
"gd" "gdscript" # Godot
"gdshader" "gdshaderinc"
"tscn" "tres" # Godot scenes/resources (text format)
"nut" # Squirrel
"angelscript" "as"
"lua" "moon" # MoonScript
# ============ PROTOCOLS & IDL ============
"proto" "protobuf" # Protocol Buffers
"thrift"
"avdl" "avsc" "avpr" # Avro
"capnp" # Cap'n Proto
"fbs" # FlatBuffers
"smithy"
"wsdl" # Web Services
"raml" # RESTful API Modeling
"swagger" "openapi"
# ============ DOMAIN-SPECIFIC ============
"tex" "latex" "sty" "cls" "bib" "bst" "dtx" "ins" "ltx"
"bib" "aux" "toc" "lof" "lot"
"rnc" "rng" # RELAX NG
"xquery" "xq" "xql" "xqm"
"sparql" "rq"
"ttl" "n3" "nt" "nq" # RDF serializations
"owl" # Web Ontology Language
"dot" "gv" # Graphviz
"puml" "plantuml" "pu" # PlantUML
"mmd" "mermaid" # Mermaid
"ditaa"
"bnf" "ebnf" # Backus-Naur Form
"abnf"
# ============ LOCALIZATION ============
"po" "pot" "mo" # Gettext
"xliff" "xlf"
"arb" "ftl" # Fluent
"resx" "resw" "resjson"
"strings" "stringsdict" # iOS
"lproj"
# ============ CERTIFICATES & KEYS ============
"pem" "crt" "cer" "der" "cert"
"key" "pub" "priv" "p12" "pfx"
"csr" "ca-bundle" "p7b" "p7c" "p7s"
"jks" "keystore" "truststore"
"ovpn" # OpenVPN
"ppk" # PuTTY
# ============ WEB SERVER CONFIGS ============
"htaccess" "htpasswd" "htdigest"
"nginx" "nginxconf"
"apache" "apache2"
"caddyfile"
"traefik"
"haproxy"
# ============ LOGS & OUTPUT ============
"log" "logs" "out" "output"
"err" "error" "errors"
"trace" "debug"
"access" "access_log" "error_log"
"syslog"
"crash" "dump" "dmp"
# ============ DIFF & PATCHES ============
"diff" "patch" "rej" "orig"
"merge" "conflict"
# ============ EDITOR CONFIGS ============
"vim" "vimrc" "gvimrc" "viminfo"
"nvim" "init.vim" "init.lua"
"emacs" "el" "elc"
"sublime-settings" "sublime-keymap" "sublime-commands"
"sublime-menu" "sublime-build" "sublime-project"
"sublime-workspace" "sublime-snippet" "sublime-completions"
"sublime-macro" "tmPreferences" "tmLanguage" "tmTheme"
"code-workspace" "code-snippets" # VS Code
"iml" "idea" # IntelliJ
# ============ MISC DEVELOPMENT ============
"ignore" "keep" "skip"
"example" "sample" "template" "stub"
"backup" "bak" "old" "tmp" "temp"
"lock" "lockfile"
"editorconfig"
"clang-format" "clang-tidy"
"astylerc"
"indent.pro"
"tags" "ctags"
"cscope"
"gdb" "gdbinit"
"lldb" "lldbinit"
"strace"
"valgrind" "suppressions"
"doxygen" "doxyfile"
# ============ PACKAGE/PROJECT METADATA ============
"manifest" "manifest.json" "manifest.xml"
"metadata" "metadata.json"
"package.json" "bower.json" "component.json"
"project" "solution" "workspace"
"modulemap" "module"
"exports"
# ============ GRAPHICS/SHADERS (Text formats) ============
"vert" "frag" "geom" "tesc" "tese" "comp" # GLSL
"vsh" "fsh" "gsh" # Common shader abbreviations
"glslv" "glslf" "glslg"
"hlsl" "fx" "fxh" "vfx"
"cginc" "shader" "shadergraph"
# ============ AUTOMATION SCRIPTS ============
"expect"
"applescript" "scpt"
"au3" # AutoIt
"ahk" # AutoHotkey
# ============ OTHER TEXT FORMATS ============
"csv" "tab" "pipe"
"pcap" "cap" # Network captures (sometimes text)
"har" # HTTP Archive
"jmx" # JMeter
"postman_collection" "postman_environment"
"http" "rest" # HTTP request files
"curl"
"eml" "mbox" # Email
"ical" "ics" "vcf" "vcard"
"opml"
"rss" "feed"
"sitemap"
"robots" "robotstxt"
"humanstxt" "securitytxt"
"webmanifest"
"well-known"
)
################################################################################
# SCRIPT EXECUTION
################################################################################
# Remove duplicates and sort
EXTENSIONS=($(echo "${EXTENSIONS[@]}" | tr ' ' '\n' | sort -u))
TOTAL=${#EXTENSIONS[@]}
SUCCESS_COUNT=0
FAIL_COUNT=0
SKIPPED=()
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ Sublime Text Default File Association Script ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
echo "Bundle ID: $BUNDLE_ID"
echo "Total extensions to process: $TOTAL"
if [ "$DRY_RUN" = true ]; then
echo "🔍 DRY RUN MODE: No changes will be made"
fi
echo ""
# Progress bar function
show_progress() {
local current=$1
local total=$2
local width=50
local percentage=$((current * 100 / total))
local filled=$((width * current / total))
local empty=$((width - filled))
printf "\r["
printf "%${filled}s" | tr ' ' '█'
printf "%${empty}s" | tr ' ' '░'
printf "] %3d%% (%d/%d)" "$percentage" "$current" "$total"
}
# Loop through each extension and set the default app
CURRENT=0
for ext in "${EXTENSIONS[@]}"; do
((CURRENT++))
if [ "$DRY_RUN" = true ]; then
echo "Would set default for: .$ext"
((SUCCESS_COUNT++))
else
# Try to set the default app
if duti -s "$BUNDLE_ID" ".$ext" all 2>/dev/null; then
((SUCCESS_COUNT++))
show_progress "$CURRENT" "$TOTAL"
else
((FAIL_COUNT++))
SKIPPED+=("$ext")
fi
fi
done
echo "" # New line after progress bar
echo ""
################################################################################
# SUMMARY & VERIFICATION
################################################################################
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ SUMMARY ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo " Total extensions processed: $TOTAL"
echo " ✅ Successful: $SUCCESS_COUNT"
echo " ❌ Failed: $FAIL_COUNT"
if [ ${#SKIPPED[@]} -gt 0 ] && [ "$DRY_RUN" = false ]; then
echo ""
echo " Failed extensions:"
for ext in "${SKIPPED[@]:0:20}"; do
echo " • $ext"
done
if [ ${#SKIPPED[@]} -gt 20 ]; then
echo " ... and $((${#SKIPPED[@]} - 20)) more"
fi
fi
echo ""
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ VERIFICATION ║"
echo "╚════════════════════════════════════════════════════════════════╝"
if [ "$DRY_RUN" = false ]; then
# Verify common extensions
VERIFY_EXTS=("txt" "md" "js" "py" "json" "html" "css" "sh" "yml" "rs" "go" "java" "cpp" "php" "rb")
echo "Checking common extensions..."
for ext in "${VERIFY_EXTS[@]}"; do
CURRENT_APP=$(duti -x "$ext" 2>/dev/null | head -n 1 || echo "Not set")
if [[ "$CURRENT_APP" == *"$BUNDLE_ID"* ]] || [[ "$CURRENT_APP" == *"Sublime Text"* ]]; then
echo " ✓ .$ext → Sublime Text"
else
echo " ✗ .$ext → $CURRENT_APP"
fi
done
echo ""
echo "💡 Tip: You may need to restart Finder or log out for all changes to take effect"
echo " Run: killall Finder"
else
echo "Dry run completed. Run without --dry-run to apply changes."
fi
echo ""
echo "✨ Done!"
# Disable nullglob
shopt -u nullglob
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment