<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:admin="http://webns.net/mvcb/"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
	<channel> 

	<title>Comments on: UNIX Recursive file renaming based on patterns</title>
	<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns/</link>
	<description>Comments on Ask MetaFilter post UNIX Recursive file renaming based on patterns</description>
	<pubDate>Thu, 17 Mar 2005 07:44:01 -0800</pubDate>
	<lastBuildDate>Thu, 17 Mar 2005 07:44:01 -0800</lastBuildDate>
	<language>en-us</language>
	<docs>http://blogs.law.harvard.edu/tech/rss</docs>
	<ttl>60</ttl>

	<item>
		<title>Question: UNIX Recursive file renaming based on patterns</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns</link>	
		<description>Unix folks: How can I recursively find all files with a certain string in their filename, replace that string with another string, and rename them with the new filename? &lt;br /&gt;&lt;br /&gt; For example, I&apos;d like to find all the files in all subfolders that contain &quot;category040&quot; and change them to &quot;category080&quot;.  So category04021.gif gets renamed to category08021.gif.&lt;br&gt;
&lt;br&gt;
I&apos;m relatively ignorant about UNIX, so forgive me if this is a no-brainer...</description>
		<guid isPermaLink="false">post:ask.metafilter.com,2005:site.16433</guid>
		<pubDate>Thu, 17 Mar 2005 07:34:54 -0800</pubDate>
		<dc:creator>turaho</dc:creator>
		
			<category>UNIX</category>
		
			<category>file_management</category>
		
	</item> <item>
		<title>By: andrew cooke</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278478</link>	
		<description>it&apos;s probably possible with just &lt;code&gt;find&lt;/code&gt;, but life&apos;s too short to work out how (or i&apos;m too stupid).  what i do is use &lt;code&gt;find&lt;/code&gt; to produce a list of files in a temp file, then emacs (which you can &quot;program&quot;) to turn that list into a list of &quot;mv&quot; commands.&lt;br&gt;
&lt;br&gt;
so, in this case, it would be something like:&lt;br&gt;
find . -name &quot;*80*&quot; -print &amp;gt; tmp&lt;br&gt;
emacs tmp&lt;br&gt;
*stuff involve ^X^(... *&lt;br&gt;
source tmp&lt;br&gt;
&lt;br&gt;
of course, if the emacs stuff above is gibberish, this won&apos;t help.  sorry.</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278478</guid>
		<pubDate>Thu, 17 Mar 2005 07:44:01 -0800</pubDate>
		<dc:creator>andrew cooke</dc:creator>
	</item><item>
		<title>By: splice</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278484</link>	
		<description>I always use perl for these things... You&apos;ll need the File::Find module installed for this application. I could eschew that and use the find command and interpret the output, but I&apos;m lazy.&lt;br&gt;
&lt;br&gt;
&lt;code&gt;&lt;br&gt;
perl -e &apos;&lt;br&gt;
use File::Find;&lt;br&gt;
&lt;br&gt;
my $dir = &quot;/top/level/directory/here&quot;;&lt;br&gt;
find(\&amp;amp;rename_files, $dir);&lt;br&gt;
&lt;br&gt;
sub rename_files {&lt;br&gt;
&amp;nbsp;&amp;nbsp;if ($File::Find::name =~ /category040/) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$oldfile = $File::Find::name;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$File::Find::name =~ s/category040/category080/;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;`mv $oldfile $File::Find::name`;&lt;br&gt;
&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&apos;&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
This should do the trick. Untested, but if you know a smidgen of perl, you can hack it to work easily, right? Same with error checking, otherwise make sure you have backups before running this blindly. And of course, this is on the command-line (perl -e), remove the appropriate parts (perl -e and backticks) to put into a script, and we should be using strict mode. Again, I&apos;m just lazy :)</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278484</guid>
		<pubDate>Thu, 17 Mar 2005 07:55:33 -0800</pubDate>
		<dc:creator>splice</dc:creator>
	</item><item>
		<title>By: togdon</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278485</link>	
		<description>In bash:&lt;br&gt;
&lt;blockquote&gt;#!/bin/bash&lt;br&gt;
for file in *;do&lt;br&gt;
newfile=$(echo $file | sed s/category040/category080/g)&lt;br&gt;
test &quot;$file&quot; != &quot;$newfile&quot; &amp;amp;&amp;amp; mv &quot;$file&quot; $newfile&lt;br&gt;
done&lt;/blockquote&gt;</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278485</guid>
		<pubDate>Thu, 17 Mar 2005 07:56:32 -0800</pubDate>
		<dc:creator>togdon</dc:creator>
	</item><item>
		<title>By: splice</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278487</link>	
		<description>Eh... Dunno what I was smoking, but I dout File::Find::name is modifiable, so store that puppy in $newfile before doing the regexp replace and do the replace on $newfile instead, like so:&lt;br&gt;
&lt;br&gt;
&lt;code&gt;&lt;br&gt;
# Store $File::Find::name in both $oldfile and $newfile&lt;br&gt;
$oldfile = $newfile = $File::Find::name;&lt;br&gt;
$newfile =~ s/category040/category080/;&lt;br&gt;
`mv $oldfile $newfile`;&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
That would probably work better. Course, I overuse perl way too much in these cases, instead of doing bash scripting and using sed, like togdon above. Probably easier. But I like perl.</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278487</guid>
		<pubDate>Thu, 17 Mar 2005 07:59:40 -0800</pubDate>
		<dc:creator>splice</dc:creator>
	</item><item>
		<title>By: casu marzu</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278489</link>	
		<description>&lt;code&gt;find . *category040* | grep  category040 | perl -p -e &apos;s/^(.*)(category040)(.*$)/mv $1$2$3 $1category080$3/&apos; | sh&lt;/code&gt;</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278489</guid>
		<pubDate>Thu, 17 Mar 2005 08:00:36 -0800</pubDate>
		<dc:creator>casu marzu</dc:creator>
	</item><item>
		<title>By: andrew cooke</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278494</link>	
		<description>why doesn&apos;t&lt;br&gt;
find . -name &quot;*80&quot; -exec mv {} `echo {} \| sed s/80/40/` \;&lt;br&gt;
work?</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278494</guid>
		<pubDate>Thu, 17 Mar 2005 08:05:07 -0800</pubDate>
		<dc:creator>andrew cooke</dc:creator>
	</item><item>
		<title>By: grouse</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278500</link>	
		<description>I got sick of the various alternatives for this so I wrote my own in Python. The nice thing about it is that it has a --dry-run option that lets me list all the changes I&apos;m &lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;br&gt;
$ renamer --help&lt;br&gt;usage: renamer [OPTION]... [FILE]...&lt;br&gt;&lt;br&gt;options:&lt;br&gt;  --version             show program&apos;s version number and exit&lt;br&gt;  -h, --help            show this help message and exit&lt;br&gt;&lt;br&gt;  Filename modifications:&lt;br&gt;    -R STR, --remove=STR&lt;br&gt;                        remove STR&lt;br&gt;    -F OLD NEW, --fixed-string=OLD NEW&lt;br&gt;                        change OLD to NEW&lt;br&gt;    -P PATTERN NEW, --perl-regexp=PATTERN NEW&lt;br&gt;                        change regexp /PATTERN/ to NEW&lt;br&gt;&lt;br&gt;  Miscellaneous:&lt;br&gt;    -r, --recursive     recurse through subdirectories&lt;br&gt;    -d, --directories   rename directories as well&lt;br&gt;    -n, --dry-run       don&apos;t actually do anything&lt;br&gt;&lt;br&gt;
&lt;/pre&gt;&lt;br&gt;
&lt;br&gt;
If you have Python 2.4 and will use it, I&apos;ll package it up and put it on the web for you.&lt;br&gt;
&lt;br&gt;
Oops, just noticed I never implemented the regexp option, but fixed-string replacement is good enough for you.</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278500</guid>
		<pubDate>Thu, 17 Mar 2005 08:11:04 -0800</pubDate>
		<dc:creator>grouse</dc:creator>
	</item><item>
		<title>By: grouse</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278502</link>	
		<description>Ahem. The nice thing about it is that it has a --dry-run option that lets me list all the changes I&apos;m &lt;strong&gt;about to make before I make them&lt;/strong&gt;. Of course it&apos;s easy enough to do that with the find alternatives by sticking echo in front of the mv, I just got sick of find+sed for something I do so often.</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278502</guid>
		<pubDate>Thu, 17 Mar 2005 08:12:17 -0800</pubDate>
		<dc:creator>grouse</dc:creator>
	</item><item>
		<title>By: plinth</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278507</link>	
		<description>Andrew it should - although, you might want to add the -n flag to mv so that it won&apos;t inadvertendly overrite an existing file, or better yet, write a script to test before doing the move and write any failures to stdout or stderr so it can be logged.  The other issue you&apos;ll have is that that it will change the first pattern it finds, you if you have a path that has an 80 in it, it will rename that and not the file.  On top of that, it will rename directories too.  Don&apos;t forget, the goal is to rename 040 to 080&lt;br&gt;
How about:&lt;br&gt;
find . -t f -name &quot;category04*&quot; -exec mv -n {} `echo {} \| sed s/category040/category080` \;</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278507</guid>
		<pubDate>Thu, 17 Mar 2005 08:19:09 -0800</pubDate>
		<dc:creator>plinth</dc:creator>
	</item><item>
		<title>By: andrew cooke</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278510</link>	
		<description>&lt;pre&gt;find . -name &quot;*80*&quot; -exec bash -c &quot;mv \$1 \`echo \$1 | sed s/80/40/\`&quot; -- {} \;&lt;/pre&gt;&lt;br&gt;
on preview - i don&apos;t know why, but i need to invoke bash again (what i posted didn&apos;t work for me with cygwin bash)</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278510</guid>
		<pubDate>Thu, 17 Mar 2005 08:26:27 -0800</pubDate>
		<dc:creator>andrew cooke</dc:creator>
	</item><item>
		<title>By: grouse</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278541</link>	
		<description>See how much simpler &lt;code&gt;renamer --recursive --fixed-string 80 40&lt;/code&gt; is? ;)</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278541</guid>
		<pubDate>Thu, 17 Mar 2005 09:01:15 -0800</pubDate>
		<dc:creator>grouse</dc:creator>
	</item><item>
		<title>By: felix</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278542</link>	
		<description>find . | perl -ne&apos;chomp; next unless -e; $oldname = $_; s/aaa/bbb/; next if -e; rename $oldname, $_&apos;&lt;br&gt;
&lt;br&gt;
&quot;Please give me a list of all file names from here down.  Perl, take each member of that list, take off any trailing whitespace that find may have generated, and as long as that file exists, save the old name, change any occurrence of &apos;aaa&apos; to &apos;bbb&apos; in that name, and unless the new name already exists, rename the file to that.  Repeat until done.&quot;&lt;br&gt;
&lt;br&gt;
No need for perl modules, and *especially* no need for python... :)</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278542</guid>
		<pubDate>Thu, 17 Mar 2005 09:02:20 -0800</pubDate>
		<dc:creator>felix</dc:creator>
	</item><item>
		<title>By: grouse</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278623</link>	
		<description>felix&apos;s one-liner will not get the expected results if you have any directories with the pattern in it, so beware. Also it renames only the first occurrence of &apos;aaa&apos;, not &quot;any&quot; of them. And you will get nasty results if you have any files with a newline in the name, althought that was asking for trouble in the first place.</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278623</guid>
		<pubDate>Thu, 17 Mar 2005 10:25:07 -0800</pubDate>
		<dc:creator>grouse</dc:creator>
	</item><item>
		<title>By: 445supermag</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278646</link>	
		<description>Doesn&apos;t anyone use Awk anymore?  Manual is online, should be a couple line program.</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278646</guid>
		<pubDate>Thu, 17 Mar 2005 10:48:28 -0800</pubDate>
		<dc:creator>445supermag</dc:creator>
	</item><item>
		<title>By: Zed_Lopez</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278696</link>	
		<description>Nope, no one uses awk anymore. &lt;br&gt;
&lt;br&gt;
&lt;code&gt;perl -MFile::Find -e &apos;find(sub {if (-f  and /category040/) { $old = $_; s/category040/category080/g; rename $old, $_}}, &quot;.&quot;)&apos;&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
Doesn&apos;t affect symbolic links, which I&apos;m considering a feature. If it&apos;s not, replace &lt;code&gt;-f $_&lt;/code&gt; with &lt;code&gt;(-f  or -l)&lt;/code&gt;.</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278696</guid>
		<pubDate>Thu, 17 Mar 2005 11:47:27 -0800</pubDate>
		<dc:creator>Zed_Lopez</dc:creator>
	</item><item>
		<title>By: turaho</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278733</link>	
		<description>Wow, there are a lot of great answers here--I&apos;d check mark all of you if I didn&apos;t think it would make this thread look silly.&lt;br&gt;
&lt;br&gt;
Anyway, I only needed a quick and dirty solution for a one-time problem with very defined parameters, so the suggestions of andrew cooke, plinth and felix were good enough for me.  But I&apos;m definitely bookmarking this thread for future reference in case massive filenaming becomes part of my job and I need a more robust solution.&lt;br&gt;
&lt;br&gt;
Thanks again, everyone.</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278733</guid>
		<pubDate>Thu, 17 Mar 2005 12:25:33 -0800</pubDate>
		<dc:creator>turaho</dc:creator>
	</item><item>
		<title>By: fvw</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278782</link>	
		<description>andrew cooke: It needs to be passed through a shell for tokenisation because you&apos;re passing the entire command to find as a single string. Try passing each element of &lt;tt&gt;ARGV&lt;/tt&gt; (ie the command and its parameters) as a separate parameter.</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278782</guid>
		<pubDate>Thu, 17 Mar 2005 13:17:53 -0800</pubDate>
		<dc:creator>fvw</dc:creator>
	</item><item>
		<title>By: andrew cooke</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278788</link>	
		<description>eh?  &lt;a href=&quot;http://ask.metafilter.com/mefi/16433#278494&quot;&gt;this&lt;/a&gt; is what didn&apos;t work.  i can&apos;t see how &lt;em&gt;Try passing each element of ARGV (ie the command and its parameters) as a separate parameter&lt;/em&gt; applies to that.  can you explain more?  (i&apos;m not sure if i&apos;m confused or you, but my second version with bash in the exec &lt;em&gt;does&lt;/em&gt; work).</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278788</guid>
		<pubDate>Thu, 17 Mar 2005 13:27:57 -0800</pubDate>
		<dc:creator>andrew cooke</dc:creator>
	</item><item>
		<title>By: sfenders</title>
		<link>http://ask.metafilter.com/16433/UNIX-Recursive-file-renaming-based-on-patterns#278833</link>	
		<description>One more nifty thing you can do in bash:&lt;br&gt;
&lt;br&gt;
for i in `find .` ; do mv $i ${i/gory080/gory040}; done</description>
		<guid isPermaLink="false">comment:ask.metafilter.com,2005:site.16433-278833</guid>
		<pubDate>Thu, 17 Mar 2005 15:42:39 -0800</pubDate>
		<dc:creator>sfenders</dc:creator>
	</item>
	</channel>
</rss>
