{"id":18925113,"url":"https://github.com/lyonsyonii/hunt-rs","last_synced_at":"2025-04-12T21:24:55.990Z","repository":{"id":38332081,"uuid":"446221435","full_name":"LyonSyonII/hunt-rs","owner":"LyonSyonII","description":"Simplified Find command made with Rust.","archived":false,"fork":false,"pushed_at":"2025-02-10T12:29:19.000Z","size":314,"stargazers_count":94,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-04T01:06:37.880Z","etag":null,"topics":["find","linux","locate","rs","rust","search"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LyonSyonII.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-09T22:52:47.000Z","updated_at":"2025-01-19T21:41:14.000Z","dependencies_parsed_at":"2024-05-22T09:27:51.021Z","dependency_job_id":"4705df77-81ee-4b9d-bad8-26c171811434","html_url":"https://github.com/LyonSyonII/hunt-rs","commit_stats":{"total_commits":231,"total_committers":5,"mean_commits":46.2,"dds":0.6017316017316017,"last_synced_commit":"2fb19be49f933110752c60f324ab5ec4ca232dee"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LyonSyonII%2Fhunt-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LyonSyonII%2Fhunt-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LyonSyonII%2Fhunt-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LyonSyonII%2Fhunt-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LyonSyonII","download_url":"https://codeload.github.com/LyonSyonII/hunt-rs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248633210,"owners_count":21136828,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["find","linux","locate","rs","rust","search"],"created_at":"2024-11-08T11:09:37.668Z","updated_at":"2025-04-12T21:24:55.953Z","avatar_url":"https://github.com/LyonSyonII.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"![](assets/capture.png)\n[![Crates.io](https://img.shields.io/crates/v/hunt?color=orange)](https://crates.io/crates/hunt)  \n**A *highly-opinionated* simplified Find command made with Rust.**  \nBy default it searches a file/folder in the working directory and divides the result between exact matches and ones that only contain the query.  \nResults will be sorted alphabetically.\n\nFor example, `hunt SomeFile /` will search \"SomeFile\" from the root directory, and the output could be:\n    \n    Contains:\n    /SomeFileIsHere\n    /home/lyon/Downloads/abcdefgSomeFileeee\n    /mnt/Files/--SomeFile--\n\n    Exact:\n    /home/lyon/SomeFile\n\nCheck the [Benchmarks](#benchmarks) for a comparison with other tools.\n## Usage\n    hunt [OPTIONS] [NAME] [SEARCH_IN_DIRS]...\n\nBy default, searches are case-insensitive, unless `[NAME]` contains an uppercase letter or the `--case-sensitive` flag is set.\n\n### Options\n    -f, --first\n            Stop when first occurrence is found\n\n    -e, --exact\n            Only search for exactly matching occurrences, any file only containing the query will be skipped\n            \n            e.g. if query is \"SomeFile\", \"I'mSomeFile\" will be skipped, as its name contains more letters than the search\n\n    -c, --canonicalize\n            If enabled, all paths will be canonicalized\n\n    -C, --case-sensitive\n            If enabled, the search will be case-sensitive\n            \n            Note that case-sensitivity will be activated automatically when the search query contains an uppercase letter\n\n    -v, --verbose\n            Print verbose output\n            \n            It'll show all errors found: e.g. \"Could not read /proc/81261/map_files\"\n\n    -s, --simple...\n            Prints without formatting (without \"Contains:\" and \"Exact:\")\n            \n            -ss Output is not sorted\n\n    -H, --hidden\n            If enabled, it searches inside hidden directories\n            \n            If not enabled, hidden directories will be skipped\n\n    --select\n            When the search is finished, choose one file between the results\n            \n            The selected file will be printed as if -ss was used\n\n    --multiselect\n            When the search is finished, choose between the results\n            \n            The selected files will be printed one after the other, separated by spaces\n\n    -S, --starts \u003cSTARTS_WITH\u003e\n            Only files that start with this will be found\n\n    -E, --ends \u003cENDS_WITH\u003e\n            Only files that end with this will be found\n\n    -t, --type \u003cFILE_TYPE\u003e\n            Specifies the type of the file\n            \n            'f' -\u003e file | 'd' -\u003e directory\n\n    -i, --ignore \u003cIGNORE_DIRS\u003e\n            Ignores this directories. The format is:\n            \n            -i dir1,dir2,dir3,...\n\n    -h, --help\n            Print help (see a summary with '-h')\n    \n    -V, --version\n            Print version\n        \nIf the `--first` flag is set, the order in which the file will be searched is `[current_dir, home_dir, root]`.  \nIf you're already in one of these directories, `current_dir` will be skipped.\n\nIf the `--hidden` flag is **not** set, hidden files/directories will be skipped.\n\n### Args\n    [NAME]  Name of the file/folder to search\n            By default, searches are case-insensitive, unless the query contains an uppercase letter.\n    \n    [SEARCH_IN_DIRS]...\n            Directories where you want to search\n            If provided, hunt will only search there\n            \n            These directories are treated independently, so if one is nested into another the\n            search will be done two times:  \n            \n            e.g. \"hunt somefile /home/user /home/user/downloads\" will search in the home\n            directory, and because /home/user/downloads is inside it, /downloads will be\n            traversed two times\n\n### Examples\n* Search for a specific file on the whole system (hunt will stop once found)  \n    \n        hunt -f -e SomeFile\n\n* Search for files containing \"SomeFile\"\n    \n        hunt SomeFile\n\n* Search file in the home directory\n    \n        hunt -e SomeFile ~/\n\n* Search file in the downloads and pictures directories\n    \n        hunt -e SomeFile ~/downloads ~/pictures\n\n* Search all files that end with \".exe\"\n    \n        hunt --ends .exe\n\n* Search all files that end with \".exe\" in the wine directory\n    \n        hunt --ends .exe ~/.wine\n\n* Search all files that start with \".\" (all hidden files)\n    \n        hunt --starts .\n\n* Search all files that end with \".exe\", start with \"M\" and contain \"wind\" in the wine directory\n\n        hunt --starts=M --ends=.exe wind ~/.wine\n\n* Search a directory named \"folder\"\n    \n        hunt -t=d folder\n\n* Search a file named \"notfolder\"\n    \n        hunt -t=f notfolder\n\n* Remove all files named \"SomeFile\"\n        \n        hunt -s -e SomeFile | xargs rm -r\n\n## Motivation\nNormally when I search for a file, I don't know the exact subdirectory where it is, so I end up searching in the whole $HOME directory.\n\nUsing the `find` command for this ended up being very slow, as it took a lot of time to traverse all the directories, and the output was also hard to read.\n\n`locate` was faster, but it didn't always find the file I was looking for, as it only searches in its database which isn't updated in real time.\n\nSeeing how `find` did not perform any parallelism at all, I decided to make a multithreaded version of it, and that's how Hunt was born.\n\nHunt is multithreaded, so it's a lot faster than `find`, and more reliable than `locate` (recent files cannot be found with it).\n\n## Installation\n[![Packaging status](https://repology.org/badge/vertical-allrepos/hunt-find.svg)](https://repology.org/project/hunt-find/versions)\n### Precompiled binaries\nDownload the latest binary from [releases](https://github.com/lyonsyonii/hunt-rs/releases).\n\nOr install with `cargo-binstall`:\n    \n    cargo binstall hunt\n\n### Compile from source\nFirst check that you have [Rust](https://www.rust-lang.org/) installed, then run\n\n    cargo install hunt\n\n## Benchmarks\nLet's compare Hunt with some of the most used tools: the [GNU **locate** and **find**](https://www.gnu.org/software/findutils/) and the very popular also written in rust, [**fd**](https://crates.io/crates/fd-find).\n\nFor benchmarking I'm using [hyperfine](https://github.com/sharkdp/hyperfine), a tool developed by the fd dev.  \nThese are done in a system with approximately 2,762,223 files, with a network drive and an external one.  \nResults on other systems may vary, so take this comparisons as a guide.  \n\nIf you want to reproduce the benchmarks, you can do so by running the `benchmarks.sh` file from this repository.\n\n\n### Searching file in ~/\nFind first occurrence of a heavily nested file in a hidden folder from the home directory.\nFile is located in `/home/user/.wine/drive_c/users/user/AppData/Local/mygame/User Data/Crashpad/reports/SomeFile`.\n\n```\nBenchmark 1: hunt --hidden --first --exact SomeFile ~/\n  Time (mean ± σ):     180.2 ms ±   7.4 ms    [User: 406.6 ms, System: 1135.9 ms]\n  Range (min … max):   167.2 ms … 198.5 ms    16 runs\n \nBenchmark 2: fd --hidden --no-ignore --glob --color=never --max-results=1 SomeFile ~/\n  Time (mean ± σ):     913.6 ms ±  52.5 ms    [User: 2584.8 ms, System: 4628.6 ms]\n  Range (min … max):   858.6 ms … 1018.6 ms    10 runs\n \nBenchmark 3: find ~/ -name SomeFile -print -quit 2\u003e/dev/null\n  Time (mean ± σ):      2.219 s ±  0.071 s    [User: 0.587 s, System: 0.988 s]\n  Range (min … max):    2.160 s …  2.395 s    10 runs\n \nBenchmark 4: locate -n 1 -A SomeFile\n  Time (mean ± σ):      1.244 s ±  0.015 s    [User: 1.231 s, System: 0.010 s]\n  Range (min … max):    1.231 s …  1.281 s    10 runs\n \nSummary\n  'hunt --hidden --first --exact SomeFile ~/' ran\n    5.07 ± 0.36 times faster than 'fd --hidden --no-ignore --glob --color=never --max-results=1 SomeFile ~/'\n    6.90 ± 0.30 times faster than 'locate -n 1 -A SomeFile'\n   12.31 ± 0.64 times faster than 'find ~/ -name SomeFile -print -quit 2\u003e/dev/null'\n```\n\n#### Hunt\n--hidden, search all files (it normally ignores hidden files and directories in the [Ignore List](#options)).  \n--first, stop when first occurrence is found.  \n--exact, only search for files/folders named \"SomeFile\", names that only contain the pattern will be skipped.  \n\n### Searching all files that contain \"SomeFile\"\nFind all occurrences of \"SomeFile\" from the root directory (worst case scenario, checking all files in the system). \n\nThe occurrences in question are:  \n```\n/home/lyon/Downloads/abcdefgSomeFileeee\n/SomeFileIsHere\n/mnt/Files/--SomeFile--\n/home/lyon/.wine/drive_c/Program Files (x86)/Internet Explorer/SomeFile\n```\n\nFor this benchmark I'll skip Locate. It's obviously faster because it doesn't traverse all the filesystem, as it is backed up by a database.  \nIt must be noted though that the file in /mnt/Files was not found, as the database does not keep record of files in other drives.  \nFor the curious, it scored a time of 486.8 ms, only 1.32 times faster than Hunt.\n\n#### Hunt\n```\nBenchmark 1: hunt -H SomeFile /\n  Time (mean ± σ):     633.6 ms ±  25.1 ms    [User: 2876.7 ms, System: 2507.5 ms]\n  Range (min … max):   589.4 ms … 671.2 ms    10 runs\n```\n\n#### Fd\n```\nBenchmark 2: fd -HI -c never SomeFile /\n  Time (mean ± σ):      1.452 s ±  0.014 s    [User: 4.116 s, System: 8.693 s]\n  Range (min … max):    1.431 s …  1.474 s    10 runs\n```\n\n#### Find\n```\nBenchmark 3: find / -name \"*SomeFile*\"\n  Time (mean ± σ):      3.473 s ±  0.144 s    [User: 1.234 s, System: 1.602 s]\n  Range (min … max):    3.374 s …  3.874 s    10 runs\n\n```\n\n#### Summary\n```\n'hunt -H SomeFile /' ran\n  2.29 ± 0.09 times faster than 'fd -HI -c never SomeFile /'\n  5.48 ± 0.31 times faster than 'find / -name \"*SomeFile*\"'\n```\n\n### Conclusion\nHunt is faster than other alternatives if you don't need a lot of features (like regex).  \nThink of it as a simple \"where did I put that file?\" solution.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flyonsyonii%2Fhunt-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flyonsyonii%2Fhunt-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flyonsyonii%2Fhunt-rs/lists"}