Ruby Tips 14 - Copy a file with a new base name

Every now and then, we want to save a file before we overwrite it. This simple code helps extract the base name, give it a new name, and then copy it to the same folder as the original file.

The method is as shown below and has comments so that the parts are clear to understand.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  def save_old_file (file)
    # nothing to do if the file is not there
    return unless File.exist?(file)

    # suffix has the date and time in it
    suffix = DateTime.now.strftime("p%Y%m%d-%H%M%S")

    dir = File.dirname(file)
    ext = File.extname(file)

    # Get the base name without the extension
    base_name_without_ext = File.basename(file, ext)

    # Constitute new name from base name, suffix and extension
    new_name = "#{base_name_without_ext}-#{suffix}#{ext}"

    # Create the full path
    new_file_path = File.join(dir, new_name)

    # Copy the original file to the new path
    puts "Backing up: #{file} -> #{new_file_path}."
    FileUtils.cp(file, new_file_path)
  end

The thing that is important here is to use File.basename with the extension so that it does not include the extension in the base name that it extracts. There are a couple of things to keep in mind:

  • File.extname extracts only the last part of the extension – so, for a file like abc.xlsx, it will extract .xlsx – So, if the file name has multiple parts to the extension, this is not fool-proof, e.g., if you used it with abc.txt.zip, you would extract out only .zip. If you already know the correct extension name, you could pass it to the File.basename as the second parameter.
  • We extracted the extension since we wanted to concatenate it back. You could just use .* as the extension if you don’t care about the extension. So, you could do File.basename(file, '.*') instead to get the base name without the extension.

I use this method often. Feel free to use it if it helps you. The code is in the public domain.

comments powered by Disqus