18

I have a group of files that have : (colon) within the name. I need to replace the : with - (dash).

Is there an easy way to do this in a script?

Sample FileName: 2013-10-11:11:52:08_055456663_045585_.txt

An Dorfer
  • 1,178
Ducky
  • 189

5 Answers5

24

A simple 1-liner should do (assumes Posix sh-compatible shell):

for f in *:*; do mv -v -- "$f" "$(echo "$f" | tr ':' '-')"; done

Explanation:

  • for ... in ...; do ...; done is a loop

  • *:* matches all files and directories in the the current directory which have : in their name

  • f is assigned in turn to each such file name in the loop

  • mv renames its first argument to the second one; -v (verbose) asks it to print what it does; this option is GNU-utils specific, so it is available on Linux but not Solaris

  • $(...) executes the code in a sub-shell and substitutes the output

  • echo prints its argument to the standard output

  • tr reads standard output and translates the characters according to the supplied map

If you are using bash, you can avoid spawning an extra shell ($()) with sub-processes (tr) by replacing $(...) with ${f//:/-}.

sds
  • 2,108
7

As stated in another post by me the Perl-based rename tool (sometimes called prename, not to be confused with the Linux native rename tool) could do the trick for you. You just need to type

rename s/:/-/g <files to rename>

This replaces every colon with a dash in all files you name at the end, i. e. 2013-10-*. Remove the g to only replace the first colon.

Here's the link to my other Post

noggerl
  • 1,359
1

If you have just one or a few files, this can do the renaming for you:

  1. Store the pattern of the file name you are targeting as a variable: p="201*".
  2. Store the old file name you want to rename: old_name=$(ls | grep $p).
  3. Store the new file name with necessary character replacements:

    new_name=$(ls | grep $p | sed 's/:/_/g')        # Using 'sed'
    
                OR
    
    new_name=$(ls | grep $p | tr ':' '_')           # Using 'tr'
    

Bonus clean up:
  a. If for uniformity's sake you want to replace the dashes (-) along with the colons (:) with underscores (_), you can do this:

    new_name=$(ls | grep $p | tr ':-' '_');

  b. If you want the last underscore (just before the .txt) gone as well, set new_name variable as:

    new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./')
  1. Now rename your file as needed: mv $old_name $new_name

         NB: mv will fail if any of the file names in the renaming operation has spaces in it. In that case, wrap the appropriate variables in quotes, like:
mv "$old_name" $new_name OR mv $old_name "$new_name" OR mv "$old_name" "$new_name"


One-liners

1a: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | sed 's/:/_/g'); mv $old_name $new_name

1b: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':' '_'); mv $old_name $new_name

2: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_'); mv $old_name $new_name

3: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./'); mv $old_name $new_name
Dut A.
  • 111
1

I'm sure a UNIX pro could do this with bash, but here's my quick and dirty version with ruby.

path_to_files = "/home/username/wrongnames/"
filenames = `ls #{path_to_files}`.split
filenames.each do |fn|
  `mv #{path_to_files + fn} #{path_to_files + fn.gsub(/:/, "-")}`
end

set path_to_files to the path to your misnamed files. save the above code in a file called rename.rb then:

username@machinename$ ruby rename.rb
shupru
  • 127
0

using renamer:

$ renamer --find ":" --replace "-" *
Lloyd
  • 121