Home > Enterprise >  Rename multiple datetime files in Unix by inserting - and _ characters
Rename multiple datetime files in Unix by inserting - and _ characters

Time:06-14

I have many files in a directory that I want to rename so that they are recognizable according to a certain convention:

SURFACE_OBS:2019062200
SURFACE_OBS:2019062206
SURFACE_OBS:2019062212
SURFACE_OBS:2019062218
SURFACE_OBS:2019062300

etc.

How can I rename them in UNIX to be as follows?

SURFACE_OBS:2019-06-22_00
SURFACE_OBS:2019-06-22_06
SURFACE_OBS:2019-06-22_12
SURFACE_OBS:2019-06-22_18
SURFACE_OBS:2019-06-23_00 

CodePudding user response:

A bash shell loop using mv and parameter expansion could do it:

for file in *:[[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]]
do
  prefix=${file%:*}
  suffix=${file#*:}
  mv -- "${file}" "${prefix}:${suffix:0:4}-${suffix:4:2}-${suffix:6:2}_${suffix:8:2}"
done

This loop picks up every file that matches the pattern:

  • * -- anything
  • : -- a colon
  • [[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]] -- 10 digits

... and then renames it by inserting dashes and and underscore in the desired locations.

I've chosen the wildcard for the loop carefully so that it tries to match the "input" files and not the renamed files. Adjust the pattern as needed if your actual filenames have edge cases that cause the wildcard to fail (and thus rename the files a second time).

CodePudding user response:

#!/bin/bash

strindex() { 
  # get position of character in string
  x="${1%%"$2"*}"
  [[ "$x" = "$1" ]] && echo -1 || echo "${#x}"
}

get_new_filename() {
  # change filenames like:  SURFACE_OBS:2019062218
  # into filenames like:    SURFACE_OBS:2019-06-22_18

  src_str="${1}"

  # add last underscore 2 characters from end of string
  final_underscore_pos=${#src_str}-2
  src_str="${src_str:0:final_underscore_pos}_${src_str:final_underscore_pos}"

  # get position of colon in string
  colon_pos=$(strindex "${src_str}" ":")
  
  # get dash locations relative to colon position
  y_dash_pos=${colon_pos} 5
  m_dash_pos=${colon_pos} 8

  # now add dashes in date
  src_str="${src_str:0:y_dash_pos}-${src_str:y_dash_pos}"
  src_str="${src_str:0:m_dash_pos}-${src_str:m_dash_pos}"
  echo "${src_str}"
}

# accept path as argument or default to /tmp/baz/data
target_dir="${1:-/tmp/baz/data}"

while read -r line ; do
  # since file renaming depends on position of colon extract 
  # base filename without path in case path has colons 
  base_dir=${line%/*}
  filename_to_change=$(basename "${line}")
  echo "mv ${line} ${base_dir}/$(get_new_filename "${filename_to_change}")"

  # find cmd attempts to exclude files that have already been renamed 
done < <(find "${target_dir}" -name 'SURFACE*' -a ! -name '*_[0-9]\{2\}$')
  • Related