Thursday, October 28, 2021

[SOLVED] How to rename multiple files with the same name when moving them from all subdirectories into one new location

Issue

I wanted to group some log files from multiple subdirectories into one new. The problem is with moving multiple files with exact same names from multiple location into one.

I wanted to use something as below, but I need to add something to change the names of the files when copying.

find . -name "raml-proxy.log" -exec mv {} raml_log_files/ \;

Solution

A bit of find and awk could produce the list of mv commands you need. Let's first assume that your log files have quiet names without newline characters:

find . -type f -name "raml-proxy.log" |
awk -v dir="raml_log_files" '{s=$0; sub(/.*\//,""); n[$0]++;
  printf("mv \"%s\" \"%s/%s.%d\"\n", s, dir, $0, n[$0])}' > rename.sh

And then, after careful inspection of file rename.sh, just execute it. Explanation: sub(/.*\//,"") removes the directory part, if any, from the current record, including the last / character. n is an associative array where the keys are the log file names and the values are a counter that increments each time a log file with that name is encountered. Demo:

$ mkdir -p a b c d
$ touch a/a b/a c/a d/b
$ find . -type f | awk -v dir="raml_log_files" '{s=$0; sub(/.*\//,""); n[$0]++;
  printf("mv \"%s\" \"%s/%s.%d\"\n", s, dir, $0, n[$0])}'
mv "./b/a" "raml_log_files/a.1"
mv "./a/a" "raml_log_files/a.2"
mv "./d/b" "raml_log_files/b.1"
mv "./c/a" "raml_log_files/a.3"

If there can be newline characters in the names of your log files we can use the NUL character as record separator, instead of the newline:

find . -type f -name "raml-proxy.log" -print0 |
awk -v dir="raml_log_files" -v RS=$'\\0' '{s=$0; sub(/.*\//,""); n[$0]++;
  printf("mv \"%s\" \"%s/%s.%d\"\n", s, dir, $0, n[$0])}' > rename.sh


Answered By - Renaud Pacalet