{"id":15971418,"url":"https://github.com/dolph/find-replace","last_synced_at":"2025-04-04T15:44:50.801Z","repository":{"id":44596381,"uuid":"453855702","full_name":"dolph/find-replace","owner":"dolph","description":"A fast find \u0026 replace shell command written in Go.","archived":false,"fork":false,"pushed_at":"2023-03-25T02:58:21.000Z","size":51,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-10T01:41:23.398Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dolph.png","metadata":{"files":{"readme":"README.md","changelog":null,"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-31T02:16:00.000Z","updated_at":"2022-02-14T22:15:33.000Z","dependencies_parsed_at":"2024-06-21T07:25:28.214Z","dependency_job_id":"18b5afbe-f74f-492f-aaee-63aff5fcdbb9","html_url":"https://github.com/dolph/find-replace","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dolph%2Ffind-replace","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dolph%2Ffind-replace/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dolph%2Ffind-replace/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dolph%2Ffind-replace/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dolph","download_url":"https://codeload.github.com/dolph/find-replace/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247208064,"owners_count":20901568,"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":[],"created_at":"2024-10-07T20:21:31.083Z","updated_at":"2025-04-04T15:44:50.781Z","avatar_url":"https://github.com/dolph.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `find-replace`\n\nA fast find \u0026amp; replace shell command.\n\n## Usage\n\nRecursively find and replace the string `alpha` with `beta` in both file names and file contents:\n\n```bash\n$ find-replace alpha beta\nRewriting ./hello-world\nRenaming ./alphabet to betabet\n```\n\n* Files with matching contents in the current working directory are atomically rewritten.\n* Files and directories are renamed.\n* Searches are performed recursively from the current working directory.\n* Searches are case sensitive.\n* `.git/` directories are skipped.\n* Binary files are ignored.\n\n## Goal\n\nThe goal of this project is to improve on a bash snippet that I've relied on for years, by making it faster. The bash:\n\n```bash\n#!/bin/bash\nset -ex\nfind . -type f -not -path './.git/*' -exec sed -i \"s/$1/$2/g\" '{}' \\;\nfind . -iname \"*$1*\" -not -path \"./.git/*\" -exec rename \"$1\" \"$2\" '{}' \\;\n```\n\n### Benchmarking\n\nIn order to recursively rename files \u0026 directories with the bash snippet above, you have to run it until it stops failing (because it's renaming directories that it has not traversed yet):\n\nFirst attempt:\n\n```\n+ find . -type f -not -path './.git/*' -exec sed -i s/virt/subvert/g '{}' ';'\n+ + find . -iname '*virt*' -not -path './.git/*' -exec rename virt subvert '{}' ';'\n+ find: ‘./doc/api_samples/os-virtual-interfaces’: No such file or directory\n+ find: ‘./nova/tests/functional/libvirt’: No such file or directory\n+ find: ‘./nova/tests/unit/virt’: No such file or directory\n+ find: ‘./nova/virt’: No such file or directory\nreal    0m5.755s\nuser    0m1.651s\nsys     0m3.893s\n```\n\nSecond attempt:\n\n```\n+ find . -type f -not -path './.git/*' -exec sed -i s/virt/subvert/g '{}' ';'\n+ + find . -iname '*virt*' -not -path './.git/*' -exec rename virt subvert '{}' ';'\n+ find: ‘./nova/tests/unit/subvert/libvirt’: No such file or directory\n+ find: ‘./nova/subvert/libvirt’: No such file or directory\nreal    0m6.680s\nuser    0m1.593s\nsys     0m4.864s\n```\n\nThird attempt:\n\n```\n+ find . -type f -not -path './.git/*' -exec sed -i s/virt/subvert/g '{}' ';'\n+ + find . -iname '*virt*' -not -path './.git/*' -exec rename virt subvert '{}' ';'\nreal    0m6.802s\nuser    0m1.705s\nsys     0m4.866s\n```\n\nSo, it effectively takes 3 attempts and a sum total of 19.237 seconds to find and replace \"virt\" with \"subvert\" in this example.\n\n#### `find-replace` v1.1.2\n\n`find-replace` v1.1.2 improves on this performance by completing the entire task in a single traversal, 98.2% faster overall (or 94.1% faster per traversal, without errors):\n\n```\n+ find-replace virt subvert\nRewriting ./.zuul.yaml\nRewriting ./HACKING.rst\nRewriting ./README.rst\n[866 lines of output removed]\nRewriting ./setup.cfg\nRewriting ./tools/run-tests.py\nRewriting ./tox.ini\nreal    0m0.351s\nuser    0m0.152s\nsys     0m0.150s\n```\n\n`find-replace` v1.1.2 is single-threaded.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdolph%2Ffind-replace","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdolph%2Ffind-replace","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdolph%2Ffind-replace/lists"}