Simply dissect and re-assemble $file
as you iterate over the matching files: ${file%/*}
gives you $file with everything after the last /
removed, and ${file##*/}
gives you $file with everything before the last /
removed; taken together ${file%/*}/old/$date-${file##*/}
will give you the "new" filename corresponding to $file
.
Presumably the date won't change in the course of running your script, so there's no point in invoking date
for each and every file; rather, store the date in a variable once, and then use that during the loop: date=$(date '+%G-%m-%d')
. (Note that modern scripts should use $(...)
rather than backticks. Also note that %
is not a "special" character and so doesn't need quoting or escaping, though as a matter of good practice the whole format string should be quoted.)
If you have a new version of Bash, you can avoid the subshell entirely by using printf -v date '%(%G-%m-%d)T' -1
instead.
You might also find it useful to use shopt -s globstar
so that you can search to arbitrary depth in the directories, and shopt -s nullglob
so that unmatched glob (wildcard) expand to "nothing" instead of the original glob pattern.
Putting these all together we get:
shopt -s globstar nullglob
date=$( date '+%G-%m-%d' )
for file in /home/*/logs/**/access.log.gz
do
target=${file%/*}/old/$date-${file##*/}
mv -vi "$file" "$target"
done