{"id":84,"date":"2012-01-16T02:52:02","date_gmt":"2012-01-16T02:52:02","guid":{"rendered":"http:\/\/joelinoff.com\/blog\/?p=84"},"modified":"2012-02-27T01:01:54","modified_gmt":"2012-02-27T01:01:54","slug":"edit-multiple-files-at-once","status":"publish","type":"post","link":"https:\/\/joelinoff.com\/blog\/?p=84","title":{"rendered":"Edit multiple files at once using change.py"},"content":{"rendered":"<p>For many years I have used a home grown tool that allows me to make simple changes to multiple files with one command. It is called <strong>change <\/strong> and has existed as csh, bash and perl incarnations over the years. I recently rewrote it in python and thought that it might be useful to others so I am publishing it. Here is an example of how it works:<\/p>\n<p>[crayon lang=&#8221;bash&#8221; toolbar=&#8221;always&#8221; title=&#8221;Usage&#8221;]<br \/>\n#!\/bin\/bash<br \/>\nfiles=$(find . -type f)<br \/>\nchange.py &#8216;Copyright (c) 2010&#8217; &#8216;Copyright (c) 2012&#8217; $files<br \/>\nchange.py &#8216;Version 1.0&#8217; &#8216;Version 1.2&#8217; $files<br \/>\n[\/crayon]<\/p>\n<p>I suspect that lots of you have written your own, similar tools. If that is the case, please look it over send me suggestions for improvements.<br \/>\n<!--more--><br \/>\nYou can download it here: <a title=\"http:\/\/projects.joelinoff.com\/change-1.0\/change.py\" href=\"http:\/\/projects.joelinoff.com\/change-1.0\/change.py\">http:\/\/projects.joelinoff.com\/change-1.0\/change.py<\/a>.<\/p>\n<p>Make sure that you call it using the python command or edit the first line to correctly access your local version of python.<\/p>\n<p>Have fun!<\/p>\n<p>Here is the on-line help (-h or &#8211;help). It explains things in a bit more detail.<\/p>\n<p>[crayon lang=&#8221;text&#8221; toolbar=&#8221;always&#8221; title=&#8221;Help&#8221;]<br \/>\n% python .\/change.py -h<\/p>\n<p>USAGE<br \/>\nchange.py [OPTIONS]<\/p>\n<p>DESCRIPTION<br \/>\nThis a tool that allows you to conveniently change text in a group<br \/>\nof files using regular expressions. It will also change file names.<\/p>\n<p>You specify the old pattern, the new pattern and the list of files.<\/p>\n<p>The patterns are in python regular expression format which makes it<br \/>\neasy to change text that contains things like forward slashes.<\/p>\n<p>Here is a detailed example thats shows how to change foo to bar.<\/p>\n<p>% ls -1<br \/>\nfoo.txt<br \/>\nfoo-bar.txt<br \/>\n% cat foo.txt<br \/>\nfoo foo<br \/>\n% cat foo-bar.txt<br \/>\nfoo foo<br \/>\n% change.py -s foo bar foo.txt foo-bar.txt<br \/>\nTotal Files Analyzed : 2<br \/>\nFiles Changed : 2<br \/>\nFiles With Content Changes : 2<br \/>\nFiles With Name Changes : 2<br \/>\nTotal Changes : 4<br \/>\nElapsed Time : 1.00 msecs<br \/>\nTime Per File : 0.50 msecs<br \/>\n% ls -1<br \/>\nbar.txt<br \/>\nbar-bar.txt<\/p>\n<p>If you want to substitute characters that used in regular<br \/>\nexpressions like &#8216;.&#8217; you must escape it with a backslash &#8216;\\.&#8217;.<br \/>\nHere is an example:<\/p>\n<p>% # Change all 3 character strings that start with &#8216;fo&#8217;.<br \/>\n% change.py &#8216;fo.&#8217; &#8216;bar&#8217; *<\/p>\n<p>% # Only change strings that have &#8216;fo&#8217; and a period: &#8216;fo.&#8217;.<br \/>\n% change.py &#8216;fo\\.&#8217; &#8216;bar&#8217; *<\/p>\n<p>If you only want to change a work use the &#8216;\\b&#8217; directive as<br \/>\nfollows:<\/p>\n<p>% # Change &#8216;foo&#8217; to &#8216;bar&#8217; but leave &#8216;foobar&#8217; alone.<br \/>\n% change.py &#8216;\\bfoo\\b&#8217; &#8216;bar&#8217; *<\/p>\n<p>OPTIONS<br \/>\n-C, &#8211;keep-contents<br \/>\nDon&#8217;t change file contents. By default file contents<br \/>\nchange.<\/p>\n<p>-d<\/p>\n<p><dir>, &#8211;dir<\/dir>&nbsp;<\/p>\n<p><dir>Output directory. By default the files are changed<\/dir>&nbsp;<\/p>\n<p><dir>in place. If this option is specified, then changed<\/dir>&nbsp;<\/p>\n<p><dir>files appear in &lt;dir&gt;\/&lt;xfn&gt; where xfn is the file<\/dir>&nbsp;<\/p>\n<p><dir>name with the unique portion of directory for all<\/dir>&nbsp;<\/p>\n<p><dir>file names in the list prepended. This reduces the<\/dir>&nbsp;<\/p>\n<p><dir>depth of the output direction. This is useful for<\/dir>&nbsp;<\/p>\n<p><dir>debugging.<\/dir>-h, &#8211;help Display this usage message.<\/p>\n<p>-n, &#8211;noop No change. It only tells you what would be changed.<\/p>\n<p>-N, &#8211;keep-names<br \/>\nDon&#8217;t change file names. By default file names change.<\/p>\n<p>-s, &#8211;stats Print out run stats.<\/p>\n<p>-v, &#8211;verbose<br \/>\nIncrease the level of verbosity.<br \/>\nThis can be specified multiple times.<\/p>\n<p>-V, &#8211;version<br \/>\nPrint the program version and exit.<\/p>\n<p>EXAMPLES<br \/>\n% # Help<br \/>\n% change.py -h<\/p>\n<p>% # Change foo to bar for the C++ files in this directory.<br \/>\n% change.py -s &#8216;foo&#8217; &#8216;bar&#8217; *.cc *.h<\/p>\n<p>% # Change old to new for all Python files in this directory<br \/>\n% # tree.<br \/>\n% change.py -s &#8216;old&#8217; &#8216;new&#8217; `find . -type f -name &#8216;*.py`<\/p>\n<p>% # Change old to new for all Python files but leave the<br \/>\n% # file names unchanged.<br \/>\n% change.py -s -N &#8216;old&#8217; &#8216;new&#8217; `find . -type f -name &#8216;*.py`<\/p>\n<p>AUTHOR<br \/>\nJoe Linoff<\/p>\n<p>VERSION<br \/>\nVersion 1.0<\/p>\n<p>LICENSE<br \/>\nThis for this change tool.<\/p>\n<p>Copyright (c) 2011 by Joe Linoff<\/p>\n<p>The change tool is free software; you can redistribute it and\/or<br \/>\nmodify it under the terms of the GNU General Public License as<br \/>\npublished by the Free Software Foundation; either version 2 of the<br \/>\nLicense, or (at your option) any later version.<\/p>\n<p>The change tool is distributed in the hope that it will be useful,<br \/>\nbut WITHOUT ANY WARRANTY; without even the implied warranty of<br \/>\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU<br \/>\nGeneral Public License for more details. You should have received<br \/>\na copy of the GNU General Public License along with the change<br \/>\ntool; if not, write to the Free Software Foundation, Inc., 59<br \/>\nTemple Place, Suite 330, Boston, MA 02111-1307 USA.<br \/>\n[\/crayon]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For many years I have used a home grown tool that allows me to make simple changes to multiple files with one command. It is called change and has existed as csh, bash and perl incarnations over the years. I recently rewrote it in python and thought that it might be useful to others so &hellip; <a href=\"https:\/\/joelinoff.com\/blog\/?p=84\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Edit multiple files at once using change.py<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[5,7],"tags":[],"_links":{"self":[{"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/84"}],"collection":[{"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=84"}],"version-history":[{"count":20,"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/84\/revisions"}],"predecessor-version":[{"id":400,"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/84\/revisions\/400"}],"wp:attachment":[{"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=84"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=84"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=84"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}