Showing off ruby to a coworker, and I want to emphasize how succinct yet
clear it can be. So I want to rename all .mp3 files to .temp, or vice versa
in the current directory -- in the shortest LOC *that you would actually write*;
not the "here's a one-liner nobody in their right mind would every write if
they had to maintain it".
Here's my first solution:
Dir.new("./").each do |file|
if file.match(/mp3$/)
File.rename(file, file.gsub(/mp3$/, 'temp'))
elsif file.match(/temp$/)
File.rename(file, file.gsub(/temp$/, 'mp3'))
end
end
Note you can NOT do the following, as it renames mp3 to temp,
then immediately renames that same file back to mp3...
Dir.new("./").each do |file|
File.rename(file, file.gsub(/mp3$/, 'temp')) if file.match(/mp3$/)
File.rename(file, file.gsub(/temp$/, 'mp3')) if file.match(/temp$/)
end
If it where a one time solution, I'd do something like this. Though
maybe I'd extract the file endings into variables, to make it easier
to change them.
mp3 = Dir['*.mp3']
temp = Dir['*.temp']
mp3.each do | fn | File.rename(fn, File.basename(fn, '.mp3') + '.temp') end
temp.each do | fn | File.rename(fn, File.basename(fn, '.temp') + '.mp3') end
regards,
Brian
···
On 18/08/05, Brock Weaver <brockweaver@gmail.com> wrote:
Showing off ruby to a coworker, and I want to emphasize how succinct yet
clear it can be. So I want to rename all .mp3 files to .temp, or vice versa
in the current directory -- in the shortest LOC *that you would actually write*;
not the "here's a one-liner nobody in their right mind would every write if
they had to maintain it".
Here's my first solution:
Dir.new("./").each do |file|
if file.match(/mp3$/)
File.rename(file, file.gsub(/mp3$/, 'temp'))
elsif file.match(/temp$/)
File.rename(file, file.gsub(/temp$/, 'mp3'))
end
end
Note you can NOT do the following, as it renames mp3 to temp,
then immediately renames that same file back to mp3...
Dir.new("./").each do |file|
File.rename(file, file.gsub(/mp3$/, 'temp')) if file.match(/mp3$/)
File.rename(file, file.gsub(/temp$/, 'mp3')) if file.match(/temp$/)
end
def switch_endings(current_ending, new_ending)
files = Dir.glob("*.#{current_ending}") do |filename|
File.rename(filename, filename.gsub(/\.#{current_ending}$/,
".#{new_ending}"))
end
end
As for doing both renames at the same time (i.e. swapping the various
endings) you can't really do that without using a third temporary ending,
so you could do:
Showing off ruby to a coworker, and I want to emphasize how succinct yet
clear it can be. So I want to rename all .mp3 files to .temp, or vice versa
in the current directory -- in the shortest LOC *that you would actually write*;
not the "here's a one-liner nobody in their right mind would every write if
they had to maintain it".
Here's my first solution:
Dir.new("./").each do |file|
if file.match(/mp3$/)
File.rename(file, file.gsub(/mp3$/, 'temp'))
elsif file.match(/temp$/)
File.rename(file, file.gsub(/temp$/, 'mp3'))
end
end
Showing off ruby to a coworker, and I want to emphasize how succinct yet
clear it can be. So I want to rename all .mp3 files to .temp, or vice versa
in the current directory -- in the shortest LOC *that you would actually write*;
not the "here's a one-liner nobody in their right mind would every write if
they had to maintain it".
Here's my first solution:
Dir.new("./").each do |file|
if file.match(/mp3$/)
File.rename(file, file.gsub(/mp3$/, 'temp'))
elsif file.match(/temp$/)
File.rename(file, file.gsub(/temp$/, 'mp3'))
end
end
Note you can NOT do the following, as it renames mp3 to temp,
then immediately renames that same file back to mp3...
Dir.new("./").each do |file|
File.rename(file, file.gsub(/mp3$/, 'temp')) if file.match(/mp3$/)
File.rename(file, file.gsub(/temp$/, 'mp3')) if file.match(/temp$/)
end
Dir.new("./").each do |file|
if file.match(/mp3$/)
File.rename(file, file.gsub(/mp3$/, 'temp'))
elsif file.match(/temp$/)
File.rename(file, file.gsub(/temp$/, 'mp3'))
end
end
You could use the tertiary operator to switch file names, but the (exp .. and .. or) is also nice for this kind of swapping thing.
Dir["*.{temp,mp3}"].each do |file|
File.rename( file, file.gsub( /\w+$/ ) { |ext| ext == 'mp3' and 'temp' or 'mp3' } )
end
If you don't want your extensions hardcoded everywhere, use an array:
exts = ['temp', 'mp3']
Dir["*.{#{exts.join ','}}"].each do |file|
File.rename( file, file.gsub( /(\w+)$/ ) { exts.detect { |x| x != $1 } } )
end
Showing off ruby to a coworker, and I want to emphasize how succinct yet
clear it can be. ...
Here's my first solution:
...
Any ideas?
I know that this is kind of heretical, but in a situation like this, I'd
rather use a shell script (I tend to inexpertly use zsh). In this case,
the simple solution is something like:
$ a=(*.mp3)
$ for f in $a; do
mv $f `basename $f .mp3`.temp
done
Pretty easy to read (I'd say more so than the Ruby, IMO) and almost a
one-liner. An easy idiom to remember, no editing required. If you need
to reverse it, then up-arrow and change the lines (or use another
variable, if needed).
However, if I had to do this as part of a larger project done in Ruby,
then I would have no hesitation to take the Ruby route (and I have done
almost exactly this at times).
My $0.02
Regards,
···
On Fri, 2005-08-19 at 01:24 +0900, Brock Weaver wrote:
Perfect! Thank you for your quick response. I decided to take the
shortcut of parallel variable assignment too, so I'm violating my own
rule a little I guess.
Anyway, thanks Brian.
···
On 8/18/05, Brian Schröder <ruby.brian@gmail.com> wrote:
On 18/08/05, Brock Weaver <brockweaver@gmail.com> wrote:
> Showing off ruby to a coworker, and I want to emphasize how succinct yet
> clear it can be. So I want to rename all .mp3 files to .temp, or vice versa
> in the current directory -- in the shortest LOC *that you would actually write*;
> not the "here's a one-liner nobody in their right mind would every write if
> they had to maintain it".
>
> Here's my first solution:
>
> Dir.new("./").each do |file|
> if file.match(/mp3$/)
> File.rename(file, file.gsub(/mp3$/, 'temp'))
> elsif file.match(/temp$/)
> File.rename(file, file.gsub(/temp$/, 'mp3'))
> end
> end
>
> Note you can NOT do the following, as it renames mp3 to temp,
> then immediately renames that same file back to mp3...
>
> Dir.new("./").each do |file|
> File.rename(file, file.gsub(/mp3$/, 'temp')) if file.match(/mp3$/)
> File.rename(file, file.gsub(/temp$/, 'mp3')) if file.match(/temp$/)
> end
>
> Any ideas?
>
> --
> Brock Weaver
> [OBC]Technique
>
>
If it where a one time solution, I'd do something like this. Though
maybe I'd extract the file endings into variables, to make it easier
to change them.
mp3 = Dir['*.mp3']
temp = Dir['*.temp']
mp3.each do | fn | File.rename(fn, File.basename(fn, '.mp3') + '.temp') end
temp.each do | fn | File.rename(fn, File.basename(fn, '.temp') + '.mp3') end
Dir.new("./").each do |file|
if file.match(/mp3$/)
File.rename(file, file.gsub(/mp3$/, 'temp'))
elsif file.match(/temp$/)
File.rename(file, file.gsub(/temp$/, 'mp3'))
end
end
You could use the tertiary operator to switch file names, but the (exp .. and .. or) is also nice for this kind of swapping thing.
Dir["*.{temp,mp3}"].each do |file|
File.rename( file, file.gsub( /\w+$/ ) { |ext| ext == 'mp3' and 'temp' or 'mp3' } )
end
If you don't want your extensions hardcoded everywhere, use an array:
exts = ['temp', 'mp3']
Dir["*.{#{exts.join ','}}"].each do |file|
File.rename( file, file.gsub( /(\w+)$/ ) { exts.detect { |x| x != $1 } } )
end
_why
gsub and backreferences? Why take that approach when File.basename is available?
def switch(old, new)
Dir["*.#{old}"].each{ |file|
new_name = File.basename(file, old) + "." + new
File.rename(file, new_name)
}
end
Sorry for being late to the party (and wildly off topic for a ruby-talk thread).
Hi ..
I know that this is kind of heretical, but in a situation like this, I'd
rather use a shell script (I tend to inexpertly use zsh). In this case,
the simple solution is something like:
$ a=(*.mp3)
$ for f in $a; do
mv $f `basename $f .mp3`.temp
done
(BTW, my local zsh doesn't like basename.)
This doesn't really answer the initial requirement though, here's
an idiomatic bash version ... although the variable mangling's a
neat trick, a lot of folks here will probably find it too much like
line noise.
MP3=`echo *.mp3`
TEMP=`echo *.temp`
for file in $MP3; do mv $file ${file%.mp3}.temp; done
for file in $TEMP; do mv $file ${file%.temp}.mp3; done
it's still not safe in terms of overwriting existing files, and there's
no question in my mind that the Ruby versions are prettier.
···
On 8/18/05, Mark Probert <probertm@acm.org> wrote:
Pretty easy to read (I'd say more so than the Ruby, IMO) and almost a
one-liner. An easy idiom to remember, no editing required. If you need
to reverse it, then up-arrow and change the lines (or use another
variable, if needed).
However, if I had to do this as part of a larger project done in Ruby,
then I would have no hesitation to take the Ruby route (and I have done
almost exactly this at times).
My $0.02
Regards,
--
-mark. (probertm at acm dot org)
--
thanks,
-pate
-------------------------
We are often unable to tell people what they need to know, because
they want to know something else, and would therefore only
misunderstand what we said
- the Raven (George MacDonald, Lilith)
Perfect! Thank you for your quick response. I decided to take the
shortcut of parallel variable assignment too, so I'm violating my own
rule a little I guess.
Note that all the offered solutions including your original version don't work if there are two files named "x.mp3" and "x.temp".
Perfect! Thank you for your quick response. I decided to take the
shortcut of parallel variable assignment too, so I'm violating my own
rule a little I guess.
Note that all the offered solutions including your original version don't work if there are two files named "x.mp3" and "x.temp".
Regards,
Pit
def switch(old, new)
Dir["*.#{old}"].each{ |file|
new_name = File.basename(file, old) + "." + new
File.rename(file, new_name) unless File.exists?(new_name)
}
end
Perfect! Thank you for your quick response. I decided to take the
shortcut of parallel variable assignment too, so I'm violating my own
rule a little I guess.
Note that all the offered solutions including your original version don't work if there are two files named "x.mp3" and "x.temp".
Sorry, Ben's version works if you choose a non-existing temporary ending.
Thank you all for your replies. I've chosen to use a cross between
Zach's and Brian's implementations.
arr1, arr2 = Dir["*.mp3"], Dir["*.temp"]
arr1.each do | fn | File.rename(fn, File.basename(fn, '.mp3') + '.temp') end
arr2.each do | fn | File.rename(fn, File.basename(fn, '.temp') + '.mp3') end
Zach's is both concise and clear -- I don't need flexibility per se;
hardcoding extensions is fine. Brian's use of File.basename instead
of regex made the script run roughly 5x faster on my XP box (I'm
renaming about 2,500 files).
···
On 8/18/05, Daniel Berger <Daniel.Berger@qwest.com> wrote:
why the lucky stiff wrote:
> Daniel Berger wrote:
>
>> gsub and backreferences? Why take that approach when File.basename is
>> available?
>>
>> def switch(old, new)
>> Dir["*.#{old}"].each{ |file|
>> new_name = File.basename(file, old) + "." + new
>> File.rename(file, new_name)
>> }
>> end
>
> You understand he's trying to swap extensions, right? (I think?) Well,
> you've got to get the extension name. And File.extname( file )[1..-1]
> is ugly.
>
> I always go for short and dirty. I steal second base!
>
> _why
Oh, he wants to switch both. Hm, ok. Still no gsub or backreferences: