├── .build-and-release.sh ├── .editorconfig ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ └── feature_request.yml ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── alfred-workflow-release.yml │ ├── markdownlint.yml │ ├── pr-title.yml │ └── stale-bot.yml ├── .gitignore ├── .markdownlint.yaml ├── .rsync-exclude ├── 0194E157-0701-47CC-996A-E69B0F976319.png ├── F51A014F-1ABC-49D4-ADA8-0B83A691533F.png ├── Justfile ├── LICENSE ├── README.md ├── icon.png ├── info.plist └── scripts ├── copy-file.js ├── file-finder.js ├── home-icloud-ignore-file └── move-to-frontmost-Finder-window.applescript /.build-and-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | #─────────────────────────────────────────────────────────────────────────────── 3 | 4 | # goto git root 5 | cd "$(git rev-parse --show-toplevel)" || return 1 6 | 7 | # Prompt for next version number 8 | current_version=$(plutil -extract version xml1 -o - info.plist | sed -n 's/.*\(.*\)<\/string>.*/\1/p') 9 | echo "current version: $current_version" 10 | echo -n " next version: " 11 | read -r next_version 12 | echo "────────────────────────" 13 | 14 | # GUARD 15 | if [[ -z "$next_version" || "$next_version" == "$current_version" ]]; then 16 | print "\033[1;31mInvalid version number.\033[0m" 17 | return 1 18 | fi 19 | 20 | # update version number in THE REPO'S `info.plist` 21 | plutil -replace version -string "$next_version" info.plist 22 | 23 | #─────────────────────────────────────────────────────────────────────────────── 24 | # INFO this assumes the local folder is named the same as the github repo 25 | # 1. update version number in LOCAL `info.plist` 26 | # 2. convenience: copy download link for current version 27 | 28 | # update version number in LOCAL `info.plist` 29 | prefs_location=$(defaults read com.runningwithcrayons.Alfred-Preferences syncfolder | sed "s|^~|$HOME|") 30 | workflow_uid="$(basename "$PWD")" 31 | local_info_plist="$prefs_location/Alfred.alfredpreferences/workflows/$workflow_uid/info.plist" 32 | if [[ -f "$local_info_plist" ]] ; then 33 | plutil -replace version -string "$next_version" "$local_info_plist" 34 | else 35 | print "\033[1;33mCould not increment version, local \`info.plist\` not found: '$local_info_plist'\033[0m" 36 | return 1 37 | fi 38 | 39 | # copy download link for current version 40 | msg="Available in the Alfred Gallery in 1-2 days, or directly by downloading the latest release here:" 41 | github_user=$(git remote --verbose | head -n1 | sed -E 's/.*github.com[:\](.*)\/.*/\1/') 42 | url="https://github.com/$github_user/$workflow_uid/releases/download/$next_version/${workflow_uid}.alfredworkflow" 43 | echo -n "$msg $url" | pbcopy 44 | 45 | #─────────────────────────────────────────────────────────────────────────────── 46 | 47 | # commit and push 48 | git add --all && 49 | git commit -m "release: $next_version" && 50 | git pull --no-progress && 51 | git push --no-progress && 52 | git tag "$next_version" && # pushing a tag triggers the github release action 53 | git push --no-progress origin --tags 54 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | max_line_length = 100 5 | end_of_line = lf 6 | charset = utf-8 7 | insert_final_newline = true 8 | indent_style = tab 9 | indent_size = 3 10 | tab_width = 3 11 | trim_trailing_whitespace = true 12 | 13 | [*.{yml,yaml}] 14 | indent_style = space 15 | indent_size = 2 16 | tab_width = 2 17 | 18 | [*.py] 19 | indent_style = space 20 | indent_size = 4 21 | tab_width = 4 22 | 23 | [*.md] 24 | indent_size = 4 25 | tab_width = 4 26 | trim_trailing_whitespace = false 27 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/en/github/administering-a-repository/managing-repository-settings/displaying-a-sponsor-button-in-your-repository 2 | 3 | custom: https://www.paypal.me/ChrisGrieser 4 | ko_fi: pseudometa 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: File a bug report 3 | title: "[Bug]: " 4 | labels: ["bug"] 5 | body: 6 | - type: checkboxes 7 | id: checklist 8 | attributes: 9 | label: Checklist 10 | options: 11 | - label: I have updated to the [latest version of this workflow](./releases/latest). 12 | required: true 13 | - label: I am using Alfred 5 or later. 14 | required: true 15 | - type: input 16 | id: alfred-version-info 17 | attributes: 18 | label: Alfred version 19 | description: Open the `Alfred Preferences.app`, go to the `General` tab. The version number is shown at the top left. 20 | placeholder: 5.5 [2251] 21 | validations: { required: true } 22 | - type: input 23 | id: macos-version-info 24 | attributes: 25 | label: macOS version 26 | description: Click on the  symbol in the menu bar and select `About This Mac`. 27 | placeholder: Sonoma 14.3 28 | validations: { required: true } 29 | - type: textarea 30 | id: bug-description 31 | attributes: 32 | label: Bug Description 33 | description: A clear and concise description of the bug. 34 | validations: { required: true } 35 | - type: textarea 36 | id: screenshot 37 | attributes: 38 | label: Relevant Screenshot 39 | description: If applicable, add screenshots or a screen recording to help explain your problem. 40 | - type: textarea 41 | id: reproduction-steps 42 | attributes: 43 | label: To Reproduce 44 | description: Steps to reproduce the problem 45 | placeholder: | 46 | For example: 47 | 1. Open Alfred. 48 | 2. Run the keyword… 49 | 3. Select… 50 | validations: { required: true } 51 | - type: textarea 52 | id: debugging-log 53 | attributes: 54 | label: Debugging Log 55 | description: You can get a debugging log by opening the workflow in Alfred preferences and pressing `⌘ + D`. A small window will open up which will log everything happening during the execution of the Workflow. Use the malfunctioning part of the workflow once more, copy the content of the log window, and paste it here. If the debugging log is long, please attach it as file instead of pasting everything in here. 56 | render: Text 57 | validations: { required: true } 58 | - type: textarea 59 | id: workflow-configuration 60 | attributes: 61 | label: Workflow Configuration 62 | description: Please add a screenshot of your [workflow configuration](https://www.alfredapp.com/help/workflows/user-configuration/). 63 | validations: { required: true } 64 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Suggest an idea 3 | title: "Feature Request: " 4 | labels: ["enhancement"] 5 | body: 6 | - type: checkboxes 7 | id: checklist 8 | attributes: 9 | label: Checklist 10 | options: 11 | - label: "I have read the plugin's documentation." 12 | required: true 13 | - label: The feature would be useful to more users than just me. 14 | required: true 15 | - type: textarea 16 | id: feature-requested 17 | attributes: 18 | label: Feature Requested 19 | description: A clear and concise description of the feature. 20 | validations: 21 | required: true 22 | - type: textarea 23 | id: screenshot 24 | attributes: 25 | label: Relevant Screenshot 26 | description: If applicable, add screenshots or a screen recording to help explain the request. 27 | 28 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | commit-message: 8 | prefix: "chore(dependabot): " 9 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## What problem does this PR solve? 2 | 3 | ## How does the PR solve it? 4 | 5 | ## Checklist 6 | - [ ] Used only `camelCase` variable names. 7 | - [ ] If functionality is added or modified, also made respective changes to the 8 | `README.md` and the internal workflow documentation. 9 | -------------------------------------------------------------------------------- /.github/workflows/alfred-workflow-release.yml: -------------------------------------------------------------------------------- 1 | name: Alfred Workflow Release 2 | 3 | on: 4 | push: 5 | tags: ["*"] 6 | 7 | env: 8 | WORKFLOW_NAME: ${{ github.event.repository.name }} 9 | 10 | #─────────────────────────────────────────────────────────────────────────────── 11 | 12 | jobs: 13 | build: 14 | runs-on: macos-latest 15 | permissions: { contents: write } 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | 20 | - name: Build .alfredworkflow 21 | run: | 22 | zip --recurse-paths --symlinks "${{ env.WORKFLOW_NAME }}.alfredworkflow" . \ 23 | --exclude "README.md" ".git*" "Justfile" ".build-and-release.sh" \ 24 | ".rsync-exclude" ".editorconfig" ".typos.toml" ".markdownlint.*" 25 | 26 | - name: Create release notes 27 | id: release_notes 28 | uses: mikepenz/release-changelog-builder-action@v5 29 | env: 30 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 31 | with: 32 | mode: "COMMIT" 33 | configurationJson: | 34 | { 35 | "label_extractor": [{ 36 | "pattern": "^(\\w+)(\\([\\w\\-\\.]+\\))?(!)?: .+", 37 | "on_property": "title", 38 | "target": "$1" 39 | }], 40 | "categories": [ 41 | { "title": "## ⚠️ Breaking changes", "labels": ["break"] }, 42 | { "title": "## 🚀 New features", "labels": ["feat", "improv"] }, 43 | { "title": "## 🛠️ Fixes", "labels": ["fix", "perf", "chore"] }, 44 | { "title": "## 👾 Other", "labels": [] } 45 | ], 46 | "ignore_labels": ["release", "bump"] 47 | } 48 | 49 | - name: Release 50 | uses: softprops/action-gh-release@v2 51 | with: 52 | token: ${{ secrets.GITHUB_TOKEN }} 53 | body: ${{ steps.release_notes.outputs.changelog }} 54 | files: ${{ env.WORKFLOW_NAME }}.alfredworkflow 55 | -------------------------------------------------------------------------------- /.github/workflows/markdownlint.yml: -------------------------------------------------------------------------------- 1 | name: Markdownlint check 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | paths: 7 | - "**.md" 8 | - ".github/workflows/markdownlint.yml" 9 | - ".markdownlint.*" # markdownlint config files 10 | pull_request: 11 | paths: 12 | - "**.md" 13 | 14 | jobs: 15 | markdownlint: 16 | name: Markdownlint 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: DavidAnson/markdownlint-cli2-action@v20 21 | with: 22 | globs: "**/*.md" 23 | -------------------------------------------------------------------------------- /.github/workflows/pr-title.yml: -------------------------------------------------------------------------------- 1 | name: PR title 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | - reopened 10 | - ready_for_review 11 | 12 | permissions: 13 | pull-requests: read 14 | 15 | jobs: 16 | semantic-pull-request: 17 | name: Check PR title 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: amannn/action-semantic-pull-request@v5 21 | env: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | with: 24 | requireScope: false 25 | subjectPattern: ^(?![A-Z]).+$ # disallow title starting with capital 26 | types: | # add `improv` to the list of allowed types 27 | improv 28 | fix 29 | feat 30 | refactor 31 | build 32 | ci 33 | style 34 | test 35 | chore 36 | perf 37 | docs 38 | break 39 | revert 40 | -------------------------------------------------------------------------------- /.github/workflows/stale-bot.yml: -------------------------------------------------------------------------------- 1 | name: Stale bot 2 | on: 3 | schedule: 4 | - cron: "18 04 * * 3" 5 | 6 | permissions: 7 | issues: write 8 | pull-requests: write 9 | 10 | jobs: 11 | stale: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Close stale issues 15 | uses: actions/stale@v9 16 | with: 17 | repo-token: ${{ secrets.GITHUB_TOKEN }} 18 | 19 | # DOCS https://github.com/actions/stale#all-options 20 | days-before-stale: 180 21 | days-before-close: 7 22 | stale-issue-label: "Stale" 23 | stale-issue-message: | 24 | This issue has been automatically marked as stale. 25 | **If this issue is still affecting you, please leave any comment**, for example "bump", and it will be kept open. 26 | close-issue-message: | 27 | This issue has been closed due to inactivity, and will not be monitored. 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac 2 | .DS_Store 3 | 4 | # Alfred 5 | prefs.plist 6 | *.alfredworkflow 7 | -------------------------------------------------------------------------------- /.markdownlint.yaml: -------------------------------------------------------------------------------- 1 | # Defaults https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml 2 | # DOCS https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md 3 | #─────────────────────────────────────────────────────────────────────────────── 4 | 5 | # MODIFIED SETTINGS 6 | blanks-around-headings: 7 | lines_below: 0 # space waster 8 | ul-style: { style: sublist } 9 | 10 | # not autofixable 11 | ol-prefix: { style: ordered } 12 | line-length: 13 | tables: false 14 | code_blocks: false 15 | no-inline-html: 16 | allowed_elements: [img, details, summary, kbd, a, br] 17 | 18 | #───────────────────────────────────────────────────────────────────────────── 19 | # DISABLED 20 | ul-indent: false # not compatible with using tabs 21 | no-hard-tabs: false # taken care of by editorconfig 22 | blanks-around-lists: false # space waster 23 | first-line-heading: false # e.g., ignore-comments 24 | no-emphasis-as-heading: false # sometimes useful 25 | -------------------------------------------------------------------------------- /.rsync-exclude: -------------------------------------------------------------------------------- 1 | # vim: ft=gitignore 2 | #─────────────────────────────────────────────────────────────────────────────── 3 | 4 | # git 5 | .git/ 6 | .gitignore 7 | 8 | # Alfred 9 | prefs.plist 10 | .rsync-exclude 11 | 12 | # docs 13 | docs/ 14 | LICENSE 15 | # INFO leading `/` -> ignore only the README in the root, not in subfolders 16 | /README.md 17 | 18 | # build 19 | Justfile 20 | .github/ 21 | .build-and-release.sh 22 | 23 | # linter & types 24 | .typos.toml 25 | .editorconfig 26 | .markdownlint.yaml 27 | jxa-globals.d.ts 28 | jsconfig.json 29 | alfred.d.ts 30 | -------------------------------------------------------------------------------- /0194E157-0701-47CC-996A-E69B0F976319.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisgrieser/alfred-quick-file-access/24b613aa880367f7209842130324bfa28c7b8cff/0194E157-0701-47CC-996A-E69B0F976319.png -------------------------------------------------------------------------------- /F51A014F-1ABC-49D4-ADA8-0B83A691533F.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisgrieser/alfred-quick-file-access/24b613aa880367f7209842130324bfa28c7b8cff/F51A014F-1ABC-49D4-ADA8-0B83A691533F.png -------------------------------------------------------------------------------- /Justfile: -------------------------------------------------------------------------------- 1 | set quiet := true 2 | 3 | # REQUIRED local workflow uses same folder name 4 | 5 | workflow_uid := `basename "$PWD"` 6 | prefs_location := `defaults read com.runningwithcrayons.Alfred-Preferences syncfolder | sed "s|^~|$HOME|"` 7 | local_workflow := prefs_location / "Alfred.alfredpreferences/workflows" / workflow_uid 8 | 9 | #─────────────────────────────────────────────────────────────────────────────── 10 | 11 | transfer-changes-FROM-local: 12 | #!/usr/bin/env zsh 13 | rsync --archive --delete --exclude-from="$PWD/.rsync-exclude" "{{ local_workflow }}/" "$PWD" 14 | git status --short 15 | 16 | transfer-changes-TO-local: 17 | #!/usr/bin/env zsh 18 | rsync --archive --delete --exclude-from="$PWD/.rsync-exclude" "$PWD/" "{{ local_workflow }}" 19 | cd "{{ local_workflow }}" 20 | print "\e[1;34mChanges at the local workflow:\e[0m" 21 | git status --short . 22 | 23 | [macos] 24 | open-local-workflow-in-alfred: 25 | #!/usr/bin/env zsh 26 | # using JXA and URI for redundancy, as both are not 100 % reliable https://www.alfredforum.com/topic/18390-get-currently-edited-workflow-uri/ 27 | open "alfredpreferences://navigateto/workflows>workflow>{{ workflow_uid }}" 28 | osascript -e 'tell application id "com.runningwithcrayons.Alfred" to reveal workflow "{{ workflow_uid }}"' 29 | 30 | release: 31 | ./.build-and-release.sh 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Christopher Grieser 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Alfred Quick File Access 2 | ![GitHub downloads](https://img.shields.io/github/downloads/chrisgrieser/alfred-quick-file-access/total?label=GitHub%20Downloads&style=plastic&logo=github) 3 | ![Alfred Gallery downloads](https://img.shields.io/badge/dynamic/yaml?url=https%3A%2F%2Fraw.githubusercontent.com%2Fchrisgrieser%2F.config%2Frefs%2Fheads%2Fmain%2FAlfred.alfredpreferences%2Falfred-workflow-download-count.yaml&style=plastic&logo=alfred&label=Gallery%20Downloads&color=%235C1F87&query=alfred-quick-file-access) 4 | ![Latest release](https://img.shields.io/github/v/release/chrisgrieser/alfred-quick-file-access?label=Latest%20Release&style=plastic) 5 | 6 | Quickly access recent files, files with a specific tag, files in the current 7 | window, files in the `Downloads` folder, or trashed files. 8 | 9 | Showcase 10 | 11 | ## Usage 12 | - Search for recently modified files in your home folder and iCloud documents 13 | with the keyword `rec`. ([Searching for recent files was always a weak 14 | point on 15 | macOS.](https://new.reddit.com/r/macapps/comments/1eiy0pa/recents_folder_on_mac_is_driving_me_crazy/)) 16 | - Access files in your `Downloads` folder via `dl`. 17 | - Search for files in the front Finder window via `win`. 18 | - Access files you have assigned a Finder tag of your choice via `tag`. 19 | - Look for files in your Trash with `trash`. 20 | 21 | For all fives cases, you can change the keyword in the workflow configuration or 22 | set a [hotkey](https://www.alfredapp.com/help/workflows/triggers/hotkey/). 23 | 24 | The following actions are available for all searches: 25 | - : Open the file. 26 | - : Move the file to your front Finder window. 27 | - : Reveal the file in Finder. 28 | - : Copy the file to the clipboard. 29 | - Y: Quick Look the file. 30 | - : *(only tag search)* Remove the tag from the file. 31 | 32 | ## Installation 33 | This workflow requires `ripgrep`: 34 | 35 | ```bash 36 | brew install ripgrep 37 | ``` 38 | 39 | [Download the Alfred workflow.](https://github.com/chrisgrieser/alfred-quick-file-access/releases/latest) 40 | 41 | ## Howto: Ignore folder for recent files search 42 | 1. Go to the folder you want to ignore. 43 | 2. Press `cmd+shift+.`, to show hidden files. 44 | 3. In that folder, create a file named `.ignore`, the file content should just 45 | be `*`. This ignores every file in that folder. (If you want more 46 | fine-grained control, the file uses the [gitignore 47 | syntax](https://git-scm.com/docs/gitignore).) 48 | 4. Press `cmd+shift+.` once more, to conceal hidden files again. 49 | 50 | ## About the developer 51 | In my day job, I am a sociologist studying the social mechanisms underlying the 52 | digital economy. For my PhD project, I investigate the governance of the app 53 | economy and how software ecosystems manage the tension between innovation and 54 | compatibility. If you are interested in this subject, feel free to get in touch. 55 | 56 | - [Website](https://chris-grieser.de/) 57 | - [Mastodon](https://pkm.social/@pseudometa) 58 | - [ResearchGate](https://www.researchgate.net/profile/Christopher-Grieser) 59 | - [LinkedIn](https://www.linkedin.com/in/christopher-grieser-ba693b17a/) 60 | 61 | Buy Me a Coffee at ko-fi.com 64 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisgrieser/alfred-quick-file-access/24b613aa880367f7209842130324bfa28c7b8cff/icon.png -------------------------------------------------------------------------------- /info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundleid 6 | de.chris-grieser.quick-file-access 7 | category 8 | ⭐️ 9 | connections 10 | 11 | 0194E157-0701-47CC-996A-E69B0F976319 12 | 13 | 14 | destinationuid 15 | DC23B294-25E4-4CEA-841A-71546D15BD89 16 | modifiers 17 | 0 18 | modifiersubtext 19 | 20 | vitoclose 21 | 22 | 23 | 24 | destinationuid 25 | 0C3BFAB7-ABFF-4D30-91C6-47855B12F496 26 | modifiers 27 | 524288 28 | modifiersubtext 29 | ⌥: Reveal in Finder 30 | vitoclose 31 | 32 | 33 | 34 | destinationuid 35 | C141CBD8-4088-42FD-9ED0-F388C8B8A0A7 36 | modifiers 37 | 1048576 38 | modifiersubtext 39 | ⌘: Move to front Finder window 40 | vitoclose 41 | 42 | 43 | 44 | destinationuid 45 | 89AAC152-1A79-4CBF-9BDD-DBBAF712F72C 46 | modifiers 47 | 262144 48 | modifiersubtext 49 | ⌃: Copy to Clipboard 50 | vitoclose 51 | 52 | 53 | 54 | destinationuid 55 | 85BA17FF-F81C-4558-A3DD-A06ED76BB023 56 | modifiers 57 | 131072 58 | modifiersubtext 59 | ⇧: Remove the tag {var:tag_prefix} {var:tag_to_search} 60 | vitoclose 61 | 62 | 63 | 64 | 046A7EDC-4CFB-42C9-B7FD-7ECB4FD32442 65 | 66 | 67 | destinationuid 68 | DC23B294-25E4-4CEA-841A-71546D15BD89 69 | modifiers 70 | 0 71 | modifiersubtext 72 | 73 | vitoclose 74 | 75 | 76 | 77 | destinationuid 78 | 0C3BFAB7-ABFF-4D30-91C6-47855B12F496 79 | modifiers 80 | 524288 81 | modifiersubtext 82 | ⌥: Reveal in Finder 83 | vitoclose 84 | 85 | 86 | 87 | destinationuid 88 | C141CBD8-4088-42FD-9ED0-F388C8B8A0A7 89 | modifiers 90 | 1048576 91 | modifiersubtext 92 | ⌘: Move to front Finder window 93 | vitoclose 94 | 95 | 96 | 97 | 0AF282F1-E1F5-47C6-B70B-F25E00EA5015 98 | 99 | 100 | destinationuid 101 | DC23B294-25E4-4CEA-841A-71546D15BD89 102 | modifiers 103 | 0 104 | modifiersubtext 105 | 106 | vitoclose 107 | 108 | 109 | 110 | destinationuid 111 | 0C3BFAB7-ABFF-4D30-91C6-47855B12F496 112 | modifiers 113 | 524288 114 | modifiersubtext 115 | ⌥: Reveal in Finder 116 | vitoclose 117 | 118 | 119 | 120 | destinationuid 121 | C141CBD8-4088-42FD-9ED0-F388C8B8A0A7 122 | modifiers 123 | 1048576 124 | modifiersubtext 125 | ⌘: Move to front Finder window 126 | vitoclose 127 | 128 | 129 | 130 | destinationuid 131 | 89AAC152-1A79-4CBF-9BDD-DBBAF712F72C 132 | modifiers 133 | 262144 134 | modifiersubtext 135 | ⌃: Copy to Clipboard 136 | vitoclose 137 | 138 | 139 | 140 | 22597717-6399-48C7-8B78-551AAD86DC01 141 | 142 | 143 | destinationuid 144 | 046A7EDC-4CFB-42C9-B7FD-7ECB4FD32442 145 | modifiers 146 | 0 147 | modifiersubtext 148 | 149 | vitoclose 150 | 151 | 152 | 153 | 2F78B362-3AF3-4AD0-BEBF-22FECBEEBB77 154 | 155 | 156 | destinationuid 157 | 0AF282F1-E1F5-47C6-B70B-F25E00EA5015 158 | modifiers 159 | 0 160 | modifiersubtext 161 | 162 | vitoclose 163 | 164 | 165 | 166 | 444EBB59-C177-4CC5-9A5C-232A6D9F7A9E 167 | 168 | 169 | destinationuid 170 | 0194E157-0701-47CC-996A-E69B0F976319 171 | modifiers 172 | 0 173 | modifiersubtext 174 | 175 | vitoclose 176 | 177 | 178 | 179 | 510F2976-FA05-4025-B2F1-BE4C2CA9783C 180 | 181 | 182 | destinationuid 183 | 6DCEA464-F1BD-49D5-9251-E455ADD73073 184 | modifiers 185 | 0 186 | modifiersubtext 187 | 188 | vitoclose 189 | 190 | 191 | 192 | 682E57FD-7381-4EB8-AB57-3FF7DFD1773F 193 | 194 | 195 | destinationuid 196 | 444EBB59-C177-4CC5-9A5C-232A6D9F7A9E 197 | modifiers 198 | 0 199 | modifiersubtext 200 | 201 | vitoclose 202 | 203 | 204 | 205 | 6DCEA464-F1BD-49D5-9251-E455ADD73073 206 | 207 | 208 | destinationuid 209 | A166CD55-3AEC-45B7-9C9F-98FD649E0258 210 | modifiers 211 | 0 212 | modifiersubtext 213 | 214 | vitoclose 215 | 216 | 217 | 218 | 72F3D736-ED6D-455D-9192-18799BE0E0E9 219 | 220 | 221 | destinationuid 222 | 2F78B362-3AF3-4AD0-BEBF-22FECBEEBB77 223 | modifiers 224 | 0 225 | modifiersubtext 226 | 227 | vitoclose 228 | 229 | 230 | 231 | 7B044726-677B-4792-A3E3-29ACE7900F6F 232 | 233 | 234 | destinationuid 235 | F51A014F-1ABC-49D4-ADA8-0B83A691533F 236 | modifiers 237 | 0 238 | modifiersubtext 239 | 240 | vitoclose 241 | 242 | 243 | 244 | 85BA17FF-F81C-4558-A3DD-A06ED76BB023 245 | 246 | 247 | destinationuid 248 | 089E6397-029E-4743-8700-45C4860B2C92 249 | modifiers 250 | 0 251 | modifiersubtext 252 | 253 | vitoclose 254 | 255 | 256 | 257 | 89AAC152-1A79-4CBF-9BDD-DBBAF712F72C 258 | 259 | 260 | destinationuid 261 | FBA872DF-C511-43B9-8018-C366115A078C 262 | modifiers 263 | 0 264 | modifiersubtext 265 | 266 | vitoclose 267 | 268 | 269 | 270 | 9E6F8450-F918-43B2-B94C-531BB5805A92 271 | 272 | 273 | destinationuid 274 | 22597717-6399-48C7-8B78-551AAD86DC01 275 | modifiers 276 | 0 277 | modifiersubtext 278 | 279 | vitoclose 280 | 281 | 282 | 283 | A166CD55-3AEC-45B7-9C9F-98FD649E0258 284 | 285 | 286 | destinationuid 287 | DC23B294-25E4-4CEA-841A-71546D15BD89 288 | modifiers 289 | 0 290 | modifiersubtext 291 | 292 | vitoclose 293 | 294 | 295 | 296 | destinationuid 297 | 0C3BFAB7-ABFF-4D30-91C6-47855B12F496 298 | modifiers 299 | 524288 300 | modifiersubtext 301 | ⌥: Reveal in Finder 302 | vitoclose 303 | 304 | 305 | 306 | destinationuid 307 | 89AAC152-1A79-4CBF-9BDD-DBBAF712F72C 308 | modifiers 309 | 262144 310 | modifiersubtext 311 | ⌃: Copy to Clipboard 312 | vitoclose 313 | 314 | 315 | 316 | C141CBD8-4088-42FD-9ED0-F388C8B8A0A7 317 | 318 | 319 | destinationuid 320 | BAE121DB-A4DB-45C3-9C13-DBB7886D8933 321 | modifiers 322 | 0 323 | modifiersubtext 324 | 325 | vitoclose 326 | 327 | 328 | 329 | D158A013-04D6-4B89-BAAC-9144298030DB 330 | 331 | 332 | destinationuid 333 | 7B044726-677B-4792-A3E3-29ACE7900F6F 334 | modifiers 335 | 0 336 | modifiersubtext 337 | 338 | vitoclose 339 | 340 | 341 | 342 | F51A014F-1ABC-49D4-ADA8-0B83A691533F 343 | 344 | 345 | destinationuid 346 | 0C3BFAB7-ABFF-4D30-91C6-47855B12F496 347 | modifiers 348 | 524288 349 | modifiersubtext 350 | ⌥: Reveal in Trash 351 | vitoclose 352 | 353 | 354 | 355 | destinationuid 356 | C141CBD8-4088-42FD-9ED0-F388C8B8A0A7 357 | modifiers 358 | 1048576 359 | modifiersubtext 360 | ⌘: Move to front Finder window 361 | vitoclose 362 | 363 | 364 | 365 | destinationuid 366 | 89AAC152-1A79-4CBF-9BDD-DBBAF712F72C 367 | modifiers 368 | 262144 369 | modifiersubtext 370 | ⌃: Copy to Clipboard 371 | vitoclose 372 | 373 | 374 | 375 | destinationuid 376 | D2B2FCCA-99A2-437E-94C0-AA67800FAAE0 377 | modifiers 378 | 0 379 | modifiersubtext 380 | 381 | vitoclose 382 | 383 | 384 | 385 | 386 | createdby 387 | Chris Grieser 388 | description 389 | Quickly access recent files, files with a specific tag, files in the current window, files in the downloads folder, or trashed files. 390 | disabled 391 | 392 | name 393 | Quick File Access 394 | objects 395 | 396 | 397 | config 398 | 399 | openwith 400 | 401 | sourcefile 402 | 403 | 404 | type 405 | alfred.workflow.action.openfile 406 | uid 407 | DC23B294-25E4-4CEA-841A-71546D15BD89 408 | version 409 | 3 410 | 411 | 412 | config 413 | 414 | action 415 | 0 416 | argument 417 | 0 418 | focusedappvariable 419 | 420 | focusedappvariablename 421 | 422 | hotkey 423 | 0 424 | hotmod 425 | 0 426 | hotstring 427 | 428 | leftcursor 429 | 430 | modsmode 431 | 0 432 | relatedAppsMode 433 | 0 434 | 435 | type 436 | alfred.workflow.trigger.hotkey 437 | uid 438 | 9E6F8450-F918-43B2-B94C-531BB5805A92 439 | version 440 | 2 441 | 442 | 443 | config 444 | 445 | alfredfiltersresults 446 | 447 | alfredfiltersresultsmatchmode 448 | 2 449 | argumenttreatemptyqueryasnil 450 | 451 | argumenttrimmode 452 | 0 453 | argumenttype 454 | 1 455 | escaping 456 | 0 457 | keyword 458 | {var:recent_keyword} 459 | queuedelaycustom 460 | 3 461 | queuedelayimmediatelyinitially 462 | 463 | queuedelaymode 464 | 0 465 | queuemode 466 | 1 467 | runningsubtext 468 | loading… 469 | script 470 | 471 | scriptargtype 472 | 1 473 | scriptfile 474 | ./scripts/file-finder.js 475 | subtext 476 | 477 | title 478 | Recently changed files in home folder and iCloud… 479 | type 480 | 8 481 | withspace 482 | 483 | 484 | type 485 | alfred.workflow.input.scriptfilter 486 | uid 487 | 046A7EDC-4CFB-42C9-B7FD-7ECB4FD32442 488 | version 489 | 3 490 | 491 | 492 | config 493 | 494 | argument 495 | 496 | passthroughargument 497 | 498 | variables 499 | 500 | keyword_from_hotkey 501 | {var:recent_keyword} 502 | 503 | 504 | type 505 | alfred.workflow.utility.argument 506 | uid 507 | 22597717-6399-48C7-8B78-551AAD86DC01 508 | version 509 | 1 510 | 511 | 512 | config 513 | 514 | path 515 | 516 | 517 | type 518 | alfred.workflow.action.revealfile 519 | uid 520 | 0C3BFAB7-ABFF-4D30-91C6-47855B12F496 521 | version 522 | 1 523 | 524 | 525 | config 526 | 527 | alfredfiltersresults 528 | 529 | alfredfiltersresultsmatchmode 530 | 2 531 | argumenttreatemptyqueryasnil 532 | 533 | argumenttrimmode 534 | 0 535 | argumenttype 536 | 1 537 | escaping 538 | 0 539 | keyword 540 | {var:frontwin_keyword} 541 | queuedelaycustom 542 | 3 543 | queuedelayimmediatelyinitially 544 | 545 | queuedelaymode 546 | 0 547 | queuemode 548 | 1 549 | runningsubtext 550 | loading… 551 | script 552 | 553 | scriptargtype 554 | 1 555 | scriptfile 556 | ./scripts/file-finder.js 557 | subtext 558 | 559 | title 560 | Search in front Finder window… 561 | type 562 | 8 563 | withspace 564 | 565 | 566 | type 567 | alfred.workflow.input.scriptfilter 568 | uid 569 | A166CD55-3AEC-45B7-9C9F-98FD649E0258 570 | version 571 | 3 572 | 573 | 574 | config 575 | 576 | action 577 | 0 578 | argument 579 | 0 580 | focusedappvariable 581 | 582 | focusedappvariablename 583 | 584 | hotkey 585 | 3 586 | hotmod 587 | 1310720 588 | hotstring 589 | F 590 | leftcursor 591 | 592 | modsmode 593 | 0 594 | relatedAppsMode 595 | 0 596 | 597 | type 598 | alfred.workflow.trigger.hotkey 599 | uid 600 | 510F2976-FA05-4025-B2F1-BE4C2CA9783C 601 | version 602 | 2 603 | 604 | 605 | config 606 | 607 | argument 608 | {query} 609 | passthroughargument 610 | 611 | variables 612 | 613 | keyword_from_hotkey 614 | {var:frontwin_keyword} 615 | 616 | 617 | type 618 | alfred.workflow.utility.argument 619 | uid 620 | 6DCEA464-F1BD-49D5-9251-E455ADD73073 621 | version 622 | 1 623 | 624 | 625 | config 626 | 627 | alfredfiltersresults 628 | 629 | alfredfiltersresultsmatchmode 630 | 2 631 | argumenttreatemptyqueryasnil 632 | 633 | argumenttrimmode 634 | 0 635 | argumenttype 636 | 1 637 | escaping 638 | 102 639 | keyword 640 | {var:custom_folder_keyword} 641 | queuedelaycustom 642 | 3 643 | queuedelayimmediatelyinitially 644 | 645 | queuedelaymode 646 | 0 647 | queuemode 648 | 1 649 | runningsubtext 650 | loading… 651 | script 652 | 653 | scriptargtype 654 | 1 655 | scriptfile 656 | ./scripts/file-finder.js 657 | subtext 658 | 659 | title 660 | Files in "{var:custom_folder}"… 661 | type 662 | 8 663 | withspace 664 | 665 | 666 | type 667 | alfred.workflow.input.scriptfilter 668 | uid 669 | 0AF282F1-E1F5-47C6-B70B-F25E00EA5015 670 | version 671 | 3 672 | 673 | 674 | config 675 | 676 | action 677 | 0 678 | argument 679 | 0 680 | focusedappvariable 681 | 682 | focusedappvariablename 683 | 684 | hotkey 685 | 3 686 | hotmod 687 | 1835008 688 | hotstring 689 | F 690 | leftcursor 691 | 692 | modsmode 693 | 0 694 | relatedAppsMode 695 | 0 696 | 697 | type 698 | alfred.workflow.trigger.hotkey 699 | uid 700 | 72F3D736-ED6D-455D-9192-18799BE0E0E9 701 | version 702 | 2 703 | 704 | 705 | config 706 | 707 | lastpathcomponent 708 | 709 | onlyshowifquerypopulated 710 | 711 | removeextension 712 | 713 | text 714 | 715 | title 716 | ℹ️ No Finder window open 717 | 718 | type 719 | alfred.workflow.output.notification 720 | uid 721 | BAE121DB-A4DB-45C3-9C13-DBB7886D8933 722 | version 723 | 1 724 | 725 | 726 | config 727 | 728 | concurrently 729 | 730 | escaping 731 | 0 732 | script 733 | 734 | scriptargtype 735 | 1 736 | scriptfile 737 | ./scripts/move-to-frontmost-Finder-window.applescript 738 | type 739 | 8 740 | 741 | type 742 | alfred.workflow.action.script 743 | uid 744 | C141CBD8-4088-42FD-9ED0-F388C8B8A0A7 745 | version 746 | 2 747 | 748 | 749 | config 750 | 751 | argument 752 | {query} 753 | passthroughargument 754 | 755 | variables 756 | 757 | keyword_from_hotkey 758 | {var:custom_folder_keyword} 759 | 760 | 761 | type 762 | alfred.workflow.utility.argument 763 | uid 764 | 2F78B362-3AF3-4AD0-BEBF-22FECBEEBB77 765 | version 766 | 1 767 | 768 | 769 | config 770 | 771 | lastpathcomponent 772 | 773 | onlyshowifquerypopulated 774 | 775 | removeextension 776 | 777 | text 778 | {query} 779 | title 780 | 📋 Copied 781 | 782 | type 783 | alfred.workflow.output.notification 784 | uid 785 | FBA872DF-C511-43B9-8018-C366115A078C 786 | version 787 | 1 788 | 789 | 790 | config 791 | 792 | alfredfiltersresults 793 | 794 | alfredfiltersresultsmatchmode 795 | 2 796 | argumenttreatemptyqueryasnil 797 | 798 | argumenttrimmode 799 | 0 800 | argumenttype 801 | 1 802 | escaping 803 | 0 804 | keyword 805 | {var:tag_keyword} 806 | queuedelaycustom 807 | 3 808 | queuedelayimmediatelyinitially 809 | 810 | queuedelaymode 811 | 0 812 | queuemode 813 | 1 814 | runningsubtext 815 | loading… 816 | script 817 | 818 | scriptargtype 819 | 1 820 | scriptfile 821 | ./scripts/file-finder.js 822 | subtext 823 | 824 | title 825 | Files tagged with {var:tag_prefix} {var:tag_to_search}… 826 | type 827 | 8 828 | withspace 829 | 830 | 831 | inboundconfig 832 | 833 | inputmode 834 | 1 835 | 836 | type 837 | alfred.workflow.input.scriptfilter 838 | uid 839 | 0194E157-0701-47CC-996A-E69B0F976319 840 | version 841 | 3 842 | 843 | 844 | config 845 | 846 | action 847 | 0 848 | argument 849 | 0 850 | focusedappvariable 851 | 852 | focusedappvariablename 853 | 854 | hotkey 855 | 13 856 | hotmod 857 | 1835008 858 | hotstring 859 | W 860 | leftcursor 861 | 862 | modsmode 863 | 0 864 | relatedAppsMode 865 | 0 866 | 867 | type 868 | alfred.workflow.trigger.hotkey 869 | uid 870 | 682E57FD-7381-4EB8-AB57-3FF7DFD1773F 871 | version 872 | 2 873 | 874 | 875 | config 876 | 877 | concurrently 878 | 879 | escaping 880 | 0 881 | script 882 | 883 | scriptargtype 884 | 1 885 | scriptfile 886 | ./scripts/copy-file.js 887 | type 888 | 8 889 | 890 | type 891 | alfred.workflow.action.script 892 | uid 893 | 89AAC152-1A79-4CBF-9BDD-DBBAF712F72C 894 | version 895 | 2 896 | 897 | 898 | config 899 | 900 | argument 901 | {query} 902 | passthroughargument 903 | 904 | variables 905 | 906 | keyword_from_hotkey 907 | {var:tag_keyword} 908 | 909 | 910 | type 911 | alfred.workflow.utility.argument 912 | uid 913 | 444EBB59-C177-4CC5-9A5C-232A6D9F7A9E 914 | version 915 | 1 916 | 917 | 918 | config 919 | 920 | alfredfiltersresults 921 | 922 | alfredfiltersresultsmatchmode 923 | 2 924 | argumenttreatemptyqueryasnil 925 | 926 | argumenttrimmode 927 | 0 928 | argumenttype 929 | 1 930 | escaping 931 | 0 932 | keyword 933 | {var:trash_keyword} 934 | queuedelaycustom 935 | 3 936 | queuedelayimmediatelyinitially 937 | 938 | queuedelaymode 939 | 0 940 | queuemode 941 | 1 942 | runningsubtext 943 | loading… 944 | script 945 | 946 | scriptargtype 947 | 1 948 | scriptfile 949 | ./scripts/file-finder.js 950 | subtext 951 | 952 | title 953 | Files in Trash… 954 | type 955 | 8 956 | withspace 957 | 958 | 959 | type 960 | alfred.workflow.input.scriptfilter 961 | uid 962 | F51A014F-1ABC-49D4-ADA8-0B83A691533F 963 | version 964 | 3 965 | 966 | 967 | config 968 | 969 | concurrently 970 | 971 | escaping 972 | 102 973 | script 974 | # Open if folder, reveal if file. 975 | # Needed as files in the trash cannot be opened. 976 | 977 | if [[ -f "$1" ]] ; then 978 | open -R "$1" 979 | elif [[ -d "$1" ]] ; then 980 | open "$1" 981 | fi 982 | scriptargtype 983 | 1 984 | scriptfile 985 | 986 | type 987 | 11 988 | 989 | type 990 | alfred.workflow.action.script 991 | uid 992 | D2B2FCCA-99A2-437E-94C0-AA67800FAAE0 993 | version 994 | 2 995 | 996 | 997 | config 998 | 999 | action 1000 | 0 1001 | argument 1002 | 0 1003 | focusedappvariable 1004 | 1005 | focusedappvariablename 1006 | 1007 | hotkey 1008 | 0 1009 | hotmod 1010 | 0 1011 | hotstring 1012 | 1013 | leftcursor 1014 | 1015 | modsmode 1016 | 0 1017 | relatedAppsMode 1018 | 0 1019 | 1020 | type 1021 | alfred.workflow.trigger.hotkey 1022 | uid 1023 | D158A013-04D6-4B89-BAAC-9144298030DB 1024 | version 1025 | 2 1026 | 1027 | 1028 | config 1029 | 1030 | argument 1031 | {query} 1032 | passthroughargument 1033 | 1034 | variables 1035 | 1036 | keyword_from_hotkey 1037 | {var:trash_keyword} 1038 | 1039 | 1040 | type 1041 | alfred.workflow.utility.argument 1042 | uid 1043 | 7B044726-677B-4792-A3E3-29ACE7900F6F 1044 | version 1045 | 1 1046 | 1047 | 1048 | config 1049 | 1050 | lastpathcomponent 1051 | 1052 | onlyshowifquerypopulated 1053 | 1054 | removeextension 1055 | 1056 | text 1057 | {query} 1058 | title 1059 | {var:tag_prefix} {var:tag_to_search} removed 1060 | 1061 | type 1062 | alfred.workflow.output.notification 1063 | uid 1064 | 089E6397-029E-4743-8700-45C4860B2C92 1065 | version 1066 | 1 1067 | 1068 | 1069 | config 1070 | 1071 | tasksettings 1072 | 1073 | new_tags 1074 | {var:tag_to_search} 1075 | recursive 1076 | 1077 | 1078 | taskuid 1079 | com.alfredapp.automation.core/files-and-folders/path.tags.remove 1080 | 1081 | type 1082 | alfred.workflow.automation.task 1083 | uid 1084 | 85BA17FF-F81C-4558-A3DD-A06ED76BB023 1085 | version 1086 | 1 1087 | 1088 | 1089 | readme 1090 | ## Usage 1091 | - Search for recently modified files in your home folder and iCloud documents 1092 | with the keyword `rec`. ([Searching for recent files was always a weak 1093 | point on 1094 | macOS.](https://new.reddit.com/r/macapps/comments/1eiy0pa/recents_folder_on_mac_is_driving_me_crazy/)) 1095 | - Access files in your Downloads-folder via `dl`. 1096 | - Search for files in the front Finder window via `win`. 1097 | - Access files you have assigned a Finder tag of your choice via `tag`. 1098 | - Look for files in your Trash with `trash`. 1099 | 1100 | For all fives cases, you can change the keyword in the workflow configuration or 1101 | set a [hotkey](https://www.alfredapp.com/help/workflows/triggers/hotkey/). 1102 | 1103 | The following actions are available for all searches: 1104 | - <kbd>⏎</kbd>: Open the file. 1105 | - <kbd>⌘</kbd><kbd>⏎</kbd>: Move the file to your front Finder window. 1106 | - <kbd>⌥</kbd><kbd>⏎</kbd>: Reveal the file in Finder. 1107 | - <kbd>⌃</kbd><kbd>⏎</kbd>: Copy the file to the clipboard. 1108 | - <kbd>⌘</kbd><kbd>Y</kbd>: Quick Look the file. 1109 | - <kbd>⇧</kbd><kbd>⏎</kbd>: *(only tag search)* Remove the tag from the file. 1110 | 1111 | ## Requirements 1112 | 1113 | ```bash 1114 | brew install ripgrep 1115 | ``` 1116 | 1117 | ## Howto: Ignore folder for recent files search 1118 | 1. Go to the folder you want to ignore. 1119 | 2. Press `cmd+shift+.`, to show hidden files. 1120 | 3. In that folder, create a file named `.ignore`, the file content should just 1121 | be `*`. This ignores every file in that folder. (If you want more 1122 | fine-grained control, the file uses the [gitignore 1123 | syntax](https://git-scm.com/docs/gitignore).) 1124 | 4. Press `cmd+shift+.` once more, to conceal hidden files again. 1125 | 1126 | --- 1127 | 1128 | Created by [Chris Grieser](https://chris-grieser.de/). 1129 | uidata 1130 | 1131 | 0194E157-0701-47CC-996A-E69B0F976319 1132 | 1133 | colorindex 1134 | 3 1135 | note 1136 | tagged 1137 | xpos 1138 | 265 1139 | ypos 1140 | 460 1141 | 1142 | 046A7EDC-4CFB-42C9-B7FD-7ECB4FD32442 1143 | 1144 | colorindex 1145 | 2 1146 | note 1147 | recent files in Home and iCloud 1148 | xpos 1149 | 265 1150 | ypos 1151 | 15 1152 | 1153 | 089E6397-029E-4743-8700-45C4860B2C92 1154 | 1155 | colorindex 1156 | 9 1157 | xpos 1158 | 890 1159 | ypos 1160 | 760 1161 | 1162 | 0AF282F1-E1F5-47C6-B70B-F25E00EA5015 1163 | 1164 | colorindex 1165 | 10 1166 | note 1167 | custom folder 1168 | xpos 1169 | 265 1170 | ypos 1171 | 315 1172 | 1173 | 0C3BFAB7-ABFF-4D30-91C6-47855B12F496 1174 | 1175 | colorindex 1176 | 12 1177 | xpos 1178 | 735 1179 | ypos 1180 | 175 1181 | 1182 | 22597717-6399-48C7-8B78-551AAD86DC01 1183 | 1184 | colorindex 1185 | 2 1186 | xpos 1187 | 185 1188 | ypos 1189 | 45 1190 | 1191 | 2F78B362-3AF3-4AD0-BEBF-22FECBEEBB77 1192 | 1193 | colorindex 1194 | 10 1195 | xpos 1196 | 185 1197 | ypos 1198 | 345 1199 | 1200 | 444EBB59-C177-4CC5-9A5C-232A6D9F7A9E 1201 | 1202 | colorindex 1203 | 3 1204 | xpos 1205 | 185 1206 | ypos 1207 | 490 1208 | 1209 | 510F2976-FA05-4025-B2F1-BE4C2CA9783C 1210 | 1211 | colorindex 1212 | 7 1213 | xpos 1214 | 30 1215 | ypos 1216 | 175 1217 | 1218 | 682E57FD-7381-4EB8-AB57-3FF7DFD1773F 1219 | 1220 | colorindex 1221 | 3 1222 | xpos 1223 | 30 1224 | ypos 1225 | 460 1226 | 1227 | 6DCEA464-F1BD-49D5-9251-E455ADD73073 1228 | 1229 | colorindex 1230 | 7 1231 | xpos 1232 | 185 1233 | ypos 1234 | 205 1235 | 1236 | 72F3D736-ED6D-455D-9192-18799BE0E0E9 1237 | 1238 | colorindex 1239 | 10 1240 | xpos 1241 | 30 1242 | ypos 1243 | 315 1244 | 1245 | 7B044726-677B-4792-A3E3-29ACE7900F6F 1246 | 1247 | colorindex 1248 | 5 1249 | xpos 1250 | 185 1251 | ypos 1252 | 630 1253 | 1254 | 85BA17FF-F81C-4558-A3DD-A06ED76BB023 1255 | 1256 | colorindex 1257 | 9 1258 | xpos 1259 | 735 1260 | ypos 1261 | 760 1262 | 1263 | 89AAC152-1A79-4CBF-9BDD-DBBAF712F72C 1264 | 1265 | colorindex 1266 | 12 1267 | note 1268 | copy file to clipboard 1269 | xpos 1270 | 735 1271 | ypos 1272 | 460 1273 | 1274 | 9E6F8450-F918-43B2-B94C-531BB5805A92 1275 | 1276 | colorindex 1277 | 2 1278 | note 1279 | DOUBLE CLICK THESE 1280 | to modify the respective hotkey 1281 | xpos 1282 | 30 1283 | ypos 1284 | 15 1285 | 1286 | A166CD55-3AEC-45B7-9C9F-98FD649E0258 1287 | 1288 | colorindex 1289 | 7 1290 | note 1291 | front Finder window 1292 | xpos 1293 | 265 1294 | ypos 1295 | 175 1296 | 1297 | BAE121DB-A4DB-45C3-9C13-DBB7886D8933 1298 | 1299 | colorindex 1300 | 12 1301 | xpos 1302 | 890 1303 | ypos 1304 | 315 1305 | 1306 | C141CBD8-4088-42FD-9ED0-F388C8B8A0A7 1307 | 1308 | colorindex 1309 | 12 1310 | note 1311 | move to front window 1312 | xpos 1313 | 735 1314 | ypos 1315 | 315 1316 | 1317 | D158A013-04D6-4B89-BAAC-9144298030DB 1318 | 1319 | colorindex 1320 | 5 1321 | xpos 1322 | 30 1323 | ypos 1324 | 600 1325 | 1326 | D2B2FCCA-99A2-437E-94C0-AA67800FAAE0 1327 | 1328 | colorindex 1329 | 9 1330 | note 1331 | open if folder, reveal if file 1332 | xpos 1333 | 735 1334 | ypos 1335 | 600 1336 | 1337 | DC23B294-25E4-4CEA-841A-71546D15BD89 1338 | 1339 | colorindex 1340 | 12 1341 | xpos 1342 | 735 1343 | ypos 1344 | 15 1345 | 1346 | F51A014F-1ABC-49D4-ADA8-0B83A691533F 1347 | 1348 | colorindex 1349 | 5 1350 | note 1351 | trash 1352 | xpos 1353 | 265 1354 | ypos 1355 | 600 1356 | 1357 | FBA872DF-C511-43B9-8018-C366115A078C 1358 | 1359 | colorindex 1360 | 12 1361 | xpos 1362 | 890 1363 | ypos 1364 | 460 1365 | 1366 | 1367 | userconfigurationconfig 1368 | 1369 | 1370 | config 1371 | 1372 | default 1373 | rec 1374 | placeholder 1375 | rec 1376 | required 1377 | 1378 | trim 1379 | 1380 | 1381 | description 1382 | recently changed in user home or iCloud 1383 | label 1384 | Keywords 1385 | type 1386 | textfield 1387 | variable 1388 | recent_keyword 1389 | 1390 | 1391 | config 1392 | 1393 | default 1394 | dl 1395 | placeholder 1396 | dl 1397 | required 1398 | 1399 | trim 1400 | 1401 | 1402 | description 1403 | custom folder 1404 | label 1405 | 1406 | type 1407 | textfield 1408 | variable 1409 | custom_folder_keyword 1410 | 1411 | 1412 | config 1413 | 1414 | default 1415 | win 1416 | placeholder 1417 | front 1418 | required 1419 | 1420 | trim 1421 | 1422 | 1423 | description 1424 | front Finder window 1425 | label 1426 | 1427 | type 1428 | textfield 1429 | variable 1430 | frontwin_keyword 1431 | 1432 | 1433 | config 1434 | 1435 | default 1436 | tag 1437 | placeholder 1438 | tag 1439 | required 1440 | 1441 | trim 1442 | 1443 | 1444 | description 1445 | tagged 1446 | label 1447 | 1448 | type 1449 | textfield 1450 | variable 1451 | tag_keyword 1452 | 1453 | 1454 | config 1455 | 1456 | default 1457 | trash 1458 | placeholder 1459 | trash 1460 | required 1461 | 1462 | trim 1463 | 1464 | 1465 | description 1466 | Trash 1467 | label 1468 | 1469 | type 1470 | textfield 1471 | variable 1472 | trash_keyword 1473 | 1474 | 1475 | config 1476 | 1477 | default 1478 | ~/Downloads 1479 | filtermode 1480 | 1 1481 | placeholder 1482 | ~/Downloads 1483 | required 1484 | 1485 | 1486 | description 1487 | 1488 | label 1489 | Custom folder 1490 | type 1491 | filepicker 1492 | variable 1493 | custom_folder 1494 | 1495 | 1496 | config 1497 | 1498 | default 1499 | wip 1500 | placeholder 1501 | wip 1502 | required 1503 | 1504 | trim 1505 | 1506 | 1507 | description 1508 | Tag to use for the tag search. 1509 | label 1510 | Finder tag 1511 | type 1512 | textfield 1513 | variable 1514 | tag_to_search 1515 | 1516 | 1517 | config 1518 | 1519 | default 1520 | 🟠 1521 | pairs 1522 | 1523 | 1524 | 🟠 1525 | 🟠 1526 | 1527 | 1528 | 🟡 1529 | 🟡 1530 | 1531 | 1532 | 🔵 1533 | 🔵 1534 | 1535 | 1536 | 🟢 1537 | 🟢 1538 | 1539 | 1540 | 🔴 1541 | 🔴 1542 | 1543 | 1544 | 🟣 1545 | 🟣 1546 | 1547 | 1548 | ⚪️ 1549 | ⚪️ 1550 | 1551 | 1552 | ⚫️ 1553 | ⚫️ 1554 | 1555 | 1556 | 1557 | description 1558 | Color of the tag. This setting is purely aesthetic so your search results match visually with the color of the tag you use. 1559 | label 1560 | 1561 | type 1562 | popupbutton 1563 | variable 1564 | tag_prefix 1565 | 1566 | 1567 | config 1568 | 1569 | defaultvalue 1570 | 1000 1571 | markercount 1572 | 9 1573 | maxvalue 1574 | 2000 1575 | minvalue 1576 | 1 1577 | onlystoponmarkers 1578 | 1579 | showmarkers 1580 | 1581 | 1582 | description 1583 | Maximum for the recent file search. High value impacts performance. 1584 | label 1585 | Max recent files 1586 | type 1587 | slider 1588 | variable 1589 | max_recent_files 1590 | 1591 | 1592 | version 1593 | 1.1.1 1594 | webaddress 1595 | chris-grieser.de 1596 | 1597 | 1598 | -------------------------------------------------------------------------------- /scripts/copy-file.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env osascript -l JavaScript 2 | // https://github.com/JXA-Cookbook/JXA-Cookbook/wiki/User-Interaction-with-Files-and-Folders#copy-a-file-to-pasteboard 3 | ObjC.import("AppKit"); 4 | 5 | /** @param {string} path */ 6 | function copyPathToClipboard(path) { 7 | const pasteboard = $.NSPasteboard.generalPasteboard; 8 | pasteboard.clearContents; 9 | const success = pasteboard.setPropertyListForType($([path]), $.NSFilenamesPboardType); 10 | return success; 11 | } 12 | 13 | /** @type {AlfredRun} */ 14 | // biome-ignore lint/correctness/noUnusedVariables: Alfred run 15 | function run(argv) { 16 | const path = argv[0]; 17 | const success = copyPathToClipboard(path); 18 | if (success) return "success"; // triggers Alfred notification 19 | } 20 | -------------------------------------------------------------------------------- /scripts/file-finder.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env osascript -l JavaScript 2 | ObjC.import("stdlib"); 3 | const app = Application.currentApplication(); 4 | app.includeStandardAdditions = true; 5 | //────────────────────────────────────────────────────────────────────────────── 6 | 7 | /** @param {string} str */ 8 | function alfredMatcher(str) { 9 | const clean = str.replace(/[-_#()[\].:;,'"`]/g, " "); 10 | return [clean, str].join(" ") + " "; 11 | } 12 | 13 | /** @return {string} path of front Finder window; `""` if there is no Finder window */ 14 | function getFrontWin() { 15 | try { 16 | const path = Application("Finder").insertionLocation().url().slice(7, -1); 17 | return decodeURIComponent(path); 18 | } catch (_error) { 19 | return ""; 20 | } 21 | } 22 | 23 | /** Necessary, as this workflow requires unique keywords to determine which kind 24 | * of search to perform. 25 | * @return {boolean} whether there are duplicates 26 | * */ 27 | function hasDuplicateKeywords() { 28 | const keywords = [ 29 | $.getenv("custom_folder_keyword"), 30 | $.getenv("recent_keyword"), 31 | $.getenv("frontwin_keyword"), 32 | $.getenv("tag_keyword"), 33 | $.getenv("trash_keyword"), 34 | ]; 35 | const uniqueKeywords = [...new Set(keywords)]; 36 | return uniqueKeywords.length !== keywords.length; 37 | } 38 | 39 | /** @param {string} msg */ 40 | function errorItem(msg) { 41 | return JSON.stringify({ items: [{ title: msg, valid: false }] }); 42 | } 43 | 44 | /** @return {string} path */ 45 | function getTrashPathQuoted() { 46 | const macosVersion = Number.parseFloat(app.systemInfo().systemVersion); 47 | let trashLocation = "$HOME/Library/Mobile Documents/"; 48 | 49 | // location dependent on macOS version: https://github.com/chrisgrieser/alfred-quick-file-access/issues/4 50 | if (macosVersion < 15) trashLocation += "com~apple~CloudDocs/"; 51 | const trashPath = trashLocation + ".Trash"; 52 | 53 | // Checking via `Application("Finder").exists()` sometimes has permission 54 | // issues because the path is in iCloud. Thus checking via `test -d` instead. 55 | const userHasIcloudDrive = app.doShellScript(`test -d "${trashPath}" || echo "no"`) !== "no"; 56 | 57 | if (userHasIcloudDrive) return `"${trashPath}"`; 58 | 59 | return ""; 60 | } 61 | 62 | //────────────────────────────────────────────────────────────────────────────── 63 | 64 | const rgIgnoreFile = 65 | $.getenv("alfred_preferences") + 66 | "/workflows/" + 67 | $.getenv("alfred_workflow_uid") + 68 | "/scripts/home-icloud-ignore-file"; 69 | 70 | // FIX for external CLIs not being recognized on older Macs 71 | const pathExport = "export PATH=/usr/local/lib:/usr/local/bin:/opt/homebrew/bin/:$PATH ; "; 72 | 73 | /** @typedef {Object} SearchConfig 74 | * @property {string} shellCmd `%s` is replaced with `dir` 75 | * @property {boolean=} shallowOutput whether the `shellCmd` performs a search of depth 1 76 | * @property {boolean=} absPathOutput whether the `shellCmd` gives absolute paths as output 77 | * @property {string=} directory where to search 78 | * @property {number=} maxFiles if not set, all files are returned 79 | * @property {string=} prefix solely for display purposes 80 | */ 81 | 82 | /** @type {Record} */ 83 | const searchConfig = { 84 | [$.getenv("recent_keyword")]: { 85 | // INFO `fd` does not allow to sort results by recency, thus using `rg` instead 86 | // CAVEAT As opposed to `fd`, `rg` does not give us folders, which is 87 | // acceptable since this searches for recent files, and modification dates 88 | // for folders are unintuitive (only affected by files one level deep). 89 | shellCmd: 90 | pathExport + 91 | `cd "%s" && rg --no-config --files --binary --sortr=modified --ignore-file="${rgIgnoreFile}"`, 92 | directory: app.pathTo("home folder"), 93 | maxFiles: Number.parseInt($.getenv("max_recent_files")), 94 | }, 95 | [$.getenv("custom_folder_keyword")]: { 96 | shellCmd: `ls -t "%s"`, 97 | directory: $.getenv("custom_folder"), 98 | shallowOutput: true, 99 | }, 100 | [$.getenv("trash_keyword")]: { 101 | // - `-maxdepth 1 -mindepth 1` is faster than `-depth 1` PERF 102 | // - not using `rg`, since it will not find folders 103 | shellCmd: `find "$HOME/.Trash" ${getTrashPathQuoted()} -maxdepth 1 -mindepth 1`, 104 | absPathOutput: true, 105 | shallowOutput: true, 106 | }, 107 | [$.getenv("tag_keyword")]: { 108 | shellCmd: `mdfind "kMDItemUserTags == ${$.getenv("tag_to_search")}"`, 109 | absPathOutput: true, 110 | prefix: $.getenv("tag_prefix"), 111 | }, 112 | [$.getenv("frontwin_keyword")]: { 113 | shellCmd: `ls -t "%s"`, 114 | directory: "%s", // inserted on runtime 115 | shallowOutput: true, 116 | }, 117 | }; 118 | 119 | //────────────────────────────────────────────────────────────────────────────── 120 | 121 | /** @type {AlfredRun} */ 122 | // biome-ignore lint/correctness/noUnusedVariables: Alfred run 123 | function run() { 124 | // DETERMINE KEYWORD 125 | if (hasDuplicateKeywords()) return errorItem("⚠️ Duplicate keywords in workflow configuration."); 126 | const keyword = // `alfred_workflow_keyword` is not set when triggered via hotkey 127 | $.NSProcessInfo.processInfo.environment.objectForKey("alfred_workflow_keyword").js || 128 | $.NSProcessInfo.processInfo.environment.objectForKey("keyword_from_hotkey").js; 129 | console.log("KEYWORD:", keyword); 130 | 131 | // PARAMETERS 132 | let { shellCmd, directory, absPathOutput, shallowOutput, maxFiles, prefix } = 133 | searchConfig[keyword]; 134 | prefix = prefix ? prefix + " " : ""; 135 | 136 | // EXECUTE SEARCH 137 | if (keyword === $.getenv("frontwin_keyword")) { 138 | directory = getFrontWin(); 139 | if (directory === "") return errorItem("⚠️ No Finder window found."); 140 | } 141 | if (directory) shellCmd = shellCmd.replace("%s", directory); 142 | console.log("SHELL COMMAND\n" + shellCmd); 143 | const stdout = app.doShellScript(shellCmd).trim(); 144 | console.log("\nSTDOUT (shortened)\n" + stdout.slice(0, 300)); 145 | if (stdout === "") return errorItem("No files found."); 146 | 147 | // CREATE ALFRED ITEMS 148 | const results = stdout 149 | .split("\r") 150 | .slice(0, maxFiles) 151 | .map((line) => { 152 | const parts = line.split("/"); 153 | const name = parts.pop() || ""; 154 | const absPath = absPathOutput ? line : directory + "/" + line; 155 | 156 | let subtitle = ""; 157 | if (!shallowOutput) { 158 | const parent = parts.join("/"); 159 | subtitle = parent.replace(/.*\/com~apple~CloudDocs/, "☁").replace(/\/Users\/\w+/, "~"); 160 | subtitle = "▸ " + subtitle; 161 | } 162 | 163 | const ext = name.split(".").pop() || ""; 164 | const imageExt = ["png", "jpg", "jpeg", "gif", "icns", "tiff", "heic"]; 165 | /** @type {AlfredIcon} */ 166 | const icon = imageExt.includes(ext) 167 | ? { path: absPath } 168 | : { path: absPath, type: "fileicon" }; 169 | 170 | /** @type {AlfredItem} */ 171 | const item = { 172 | title: prefix + name, 173 | subtitle: subtitle, 174 | arg: absPath, 175 | quicklookurl: absPath, 176 | type: "file:skipcheck", 177 | match: alfredMatcher(name), 178 | icon: icon, 179 | }; 180 | if (keyword === $.getenv("frontwin_keyword")) { 181 | item.mods = { 182 | cmd: { subtitle: "⛔ Already front window", valid: false } 183 | } 184 | } 185 | return item; 186 | }) 187 | 188 | // INFO do not use Alfred's caching mechanism, since it does not work with 189 | // the `alfred_workflow_keyword` environment variable https://www.alfredforum.com/topic/21754-wrong-alfred-55-cache-used-when-using-alternate-keywords-like-foobar/#comment-113358 190 | // (Also, it would interfere with the results needing to be live.) 191 | return JSON.stringify({ items: results }); 192 | } 193 | -------------------------------------------------------------------------------- /scripts/home-icloud-ignore-file: -------------------------------------------------------------------------------- 1 | # vim: ft=gitignore 2 | #─────────────────────────────────────────────────────────────────────────────── 3 | 4 | Icon[ ] 5 | .DS_Store 6 | 7 | **/*.app/** 8 | *.{photos,music,tv}library 9 | Photo Booth Library 10 | 11 | #─────────────────────────────────────────────────────────────────────────────── 12 | 13 | # ignore everything in `Library` except iCloud documents (`com~apple~CloudDocs`) 14 | # needs to be written this convoluted way since gitignore syntax does not search 15 | # ignored directories https://stackoverflow.com/a/5285539/22114136 16 | /Library/* 17 | !/Library/Mobile Documents/ 18 | /Library/Mobile Documents/* 19 | !/Library/Mobile Documents/com~apple~CloudDocs/ 20 | -------------------------------------------------------------------------------- /scripts/move-to-frontmost-Finder-window.applescript: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env osascript 2 | 3 | # INFO use "Finder window" instead of "window" to target only regular 4 | # windows https://www.reddit.com/r/applescript/comments/uz9axo/comment/iayjrn4/?context=3 5 | 6 | on run argv 7 | set itemPath to item 1 of argv 8 | 9 | tell application "Finder" 10 | activate 11 | 12 | if ((count Finder windows) = 0) then return "No Window open" 13 | set targetFolder to (target of Finder window 1 as alias) 14 | 15 | set sourceItem to (itemPath as POSIX file) 16 | move sourceItem to targetFolder with replacing 17 | 18 | end tell 19 | end run 20 | --------------------------------------------------------------------------------