How do I rename list of files with dateformat

Hello,

I have a list of files like

-rw-rw-r-- 1 rails rails  8463005 Jul 27 04:02 find_or.log.3.gz
-rw-rw-r-- 1 rails rails 33786339 Jul 27 04:02 pro.log.10.gz
-rw-rw-r-- 1 rails rails 44815467 Aug  3 04:02 pro.log.9.gz
-rw-rw-r-- 1 rails rails 81562896 Aug  4 04:02 pro.log.8.gz
-rw-rw-r-- 1 rails rails 80073289 Aug  5 04:03 blap.log.7.gz
-rw-rw-r-- 1 rails rails  8867231 Aug  6 04:02 fea_or.log.2.gz
-rw-rw-r-- 1 rails rails 81441609 Aug  6 04:03 pro.log.6.gz
-rw-rw-r-- 1 rails rails 72789502 Aug  7 04:03 pro.log.5.gz

I need to rename these like

pro.log.5.gz to pro.log-20120807.gz
blap.log.7.gz to blap.log-20120805.gz

Basically using date of last entry of each log

Please advise the best way.

Thanks
Ashok

What is the format of your log files? How do you determine the date of the last entry in the log? What do you want to do if the date of the last entry in two log files is the same?

Instead of using last log entry date

Say when I list ls -l

-rw-rw-r-- 1 rails rails 44815467 Aug  3 04:02 pro.log.9.gz

I need to rename using "Aug 3" like pro.log.20120803.gz

My idea is to use a script like

for i in `ls *.gz`;

do
DAT=`ls -l $i  | awk '{print $6 $7}'`

Here I need a logic on how to convert $DAT values to equivalent 20120803
into say $NDAT

FN=`ls $i | cut -d'.' -f1`

mv $FN $FN.log-$NDAT.gz
done

Thanks
Ashok

The following script should do what you want. It limits itself to features specified by POSIX, except for its use of the m[] associative array variable. This is a common feature in ksh on most available systems. If your ksh doesn't support associative array variables, it could easily be replaced by a function that would return a two digit string representing the abbreviated month name that would be passed in as an argument.

#!/bin/ksh
cm=$(date +%m)	# current month as 2 deciml digits
cy=$(date +%Y)	# current year as 4 or more decimal digits
ec=0		# final exit code
ly=$((cy - 1))	# last year as 4 or more decimal digits
typeset -A m	# translation table abbreviated month name -> 2 digit month
m[Jan]=01; m[Feb]=02; m[Mar]=03; m[Apr]=04; m[May]=05; m[Jun]=06
m[Jul]=07; m[Aug]=08; m[Sep]=09; m[Oct]=10; m[Nov]=11; m[Dec]=12
for i in *.log.*.gz
do
	$ According to POSIX, the last command in a pipeline MAY be run
	# in a separate shell execution environment.  It is forced into
	# a separate execution environment here by the $(...) to make it
	# portable to any system.  The $(...) returns the value of $ec
	# it isn't exported to the execution environment of the rest of
	# this script otherwise.  If any errors are reported in the
	# subshell, their diagnostics are written to stderr (file
	# descriptor 2).  No output from the subshell is written to
	# stdout (file descriptor 1).  Note that if the move command is
	# commented out and replaced by an echo, the echo output must be
	# written to stderr!  POSIX allows shells to run the last
	# command in a mult-command pipeline in the current shell
	# execution environment as an extension.
	ls -l "$i" | ec=$( read x x x x x mnth day time file
	if [ "$file" == "" ] # only true if ls failed
	then 	printf "%s: ls failed: \"%s\"\n" "$0" "$i" >&2
		if [ $ec -eq 0 ] # preserve exit code from a failed mv command
		then	ec=100
		fi
		echo $ec
		continue
	fi
	mon=${m[$mnth]}
	if [ "${time%:+([0-9])}" == "$time" ]
	then	# No <colon> in $time means $time is a year instead of a time
		# because the date is in the future or more than six months old.
		year=$time
	elif [ "$mon" -gt $cm ]
	then	# $mon > $cm in the current year, assume it is last year
		year=$ly
	else	year=$cy # otherwise, year is assumed to be current year
	fi
	new="$(printf "%s.log-%d%02d%02d.gz" "${file%%.log.*.gz}" \
	    $year $mon $day)"
	if [ -e "$new" ] # true if $new already exists
	then	# print diagnostic; could concatenate log files instead
		printf "%s: target exists: mv \"%s\" \"%s\" not executed\n" \
		    "$0" "$file" "$new" >&2
		if [ $ec -eq 0 ] # preserve exit code from a failed mv command
		then	ec=101
		fi
		echo $ec
		continue
	fi
	# exactly one of the next two lines must be a comment (# in column 1)
#	mv "$file" "$new"
	echo mv "$file" "$new" >&2
	save=$?
	if [ $save -ne 0 ]
	then	printf "%s: mv failed: mv \"%s\" \"%s\"\n" /
		    "$0" "$file" "$new" >&2
		ec=$save
	fi
	echo $ec)
done
exit $ec

Note that the logic for setting the year to the previous year for entries
where ls -l displays the time of day instead of the year (for entries
less than six months old) hasn't been tested since this code was written
in the 2nd half of the year (and I didn't want to reset my system clock
to test this case).

1 Like

Given the command stat exists on your system and it accepts the --printf option,

stat --printf "%x %n" filename

will output sth. like

2012-08-14 15:58:24.895007883 +0200 filename

So reassembling the fields with cut , sed , or awk will do what you require.

1 Like

No. On my system (Mac OS X version 10.7.4) the command:

stat --printf "%x %n" filename

produces the following message on stderr:

stat: illegal option -- -
usage: stat [-FlLnqrsx] [-f format] [-t timefmt] [file ...]

Some systems will produce the output you specified.
Some systems don't provide a stat utility at all. I try to stick to POSIX standard behavior in the examples I post on this forum. I did use non-standard ksh array variables, but I documented that fact and don't know of any recent system that has a ksh that doesn't support them.

1 Like

Then you are in the lucky position to tell stat how to output the date using your desired timefmt.

Accepted. Good point. Still my intention was to give ideas to the requestor on how to achieve the result so he/she can dream up a best fit solution.

1 Like

Agreed. Apple's stat(1) man page's description of how to do this is rather opaque and doesn't include any examples for this issue. But the command:

stat -t "%Y%m%d" -f "%Sm%n" file

does give output in the format needed for this script (YYYYMMDD) on OS X (and would greatly simplify the script I provided).

Although this site's OpenSolaris 2009.06 Man Page Set includes a stat(1) man page, I can't find a stat(1) man page for Solaris 10 or 11 and I don't remember there being a stat utility on the Solaris systems I used to use.