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