I have a bunch of files with this naming convention:
file01_2018-10-05_123456.pdf
file01_2018-10-06_443352.pdf
file02_2019-09-20_222222.pdf
file02_2019-01-27_246821.pdf
file03_2017-11-22_654321.pdf
file03_2017-04-14_987654.pdf
I have a script that finds the most recent of each file number (file01
-file03
) and renames it to T3031
, T3032
, T3033
, cuts off everything after the first 6 chars and appends the file's last-modified date. They end up looking like this (which is exactly what I want):
T3031-2018Oct06.pdf
T3032-2019Sep20.pdf
T3033-2017Nov22.pdf
It's just that the script seems long and ugly to me (there are 17 loops for file01
-file17
). I'm hoping someone has a more elegant solution.
Here's part of what I have:
for F in $(ls -t | grep file01 | head -1)
do
RUNDATE="$(date -r $F %Y%b%d)"
a="$(echo $F | head -c6)"
b="$(echo "$a" | sed 's/file01/T3031/')"
mv "$F" "${b}-${RUNDATE}.pdf" 2> /dev/null
done
for F in $(ls -t | grep file02 | head -1)
do
RUNDATE="$(date -r $F %Y%b%d)"
a="$(echo $F | head -c6)"
b="$(echo "$a" | sed 's/file02/T3032/')"
mv "$F" "${b}-${RUNDATE}.pdf" 2> /dev/null
done
for F in $(ls -t | grep file03 | head -1)
do
RUNDATE="$(date -r $F %Y%b%d)"
a="$(echo $F | head -c6)"
b="$(echo "$a" | sed 's/file03/T3033/')"
mv "$F" "${b}-${RUNDATE}.pdf" 2> /dev/null
done
I'm new to script writing and this is my first one (also new to StackOverflow). Thanks in advance
CodePudding user response:
This might work for you (GNU sort and rename):
ls -1 file* |
sort -t_ -k1,1 -k2,2r file1 |
sort -ut_ -k1,1 |
rename -n 'm/^[^_]*(\d\d)_(\d{4})-(\d{2})-(\d{2})_\d (\..*)/;
my $f = 3030 $1;
my @m = ("XXX","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
$_ = sprintf "T%d-$2%s$4$5", $f, $m[$3]'
List out the required file
s.
Sort the list by file number and reversed date order.
Remove all but the first of each file number.
Use rename
to format the file names.
N.B. Once the file formats agree with your requirements, remove the -n
option for rename
and the files will be renamed.
CodePudding user response:
First of all, don't parse the output of ls
A shell loop:
for file in file*.pdf
do
mtime=$(date -r "$file" ' %Y%b%d')
num=${file%%_*} # remove the first "_" and all following
num=${num#file} # remove the "file" prefix
num=$(( 3030 10#$num )) # force base-10 interpretation of invalid octal "08" and "09"
mv -v "$file" "T${num}-${mtime}.pdf"
done
Or using the rename
command (remove the -n
option if it looks right)
rename -MPOSIX=strftime -n '
s{file(\d ).*}{
sprintf "T%d-%s.pdf", 3030 $1, strftime("%Y%b%d", localtime((stat)[9]))
}e
' file*pdf
CodePudding user response:
!/bin/bash
for n in 0{1..9} {10..17};
#iterate thru 17 numbers with 01,02,etc
do
for f in *;
do
filename="$( echo $f | grep file$n )";
if [[ -z $filename ]];
then echo -ne "No not here..\r";
#add file to the list of files if found
else echo $filename >> LOG"$n".txt;sleep .1;fi;
unset filename;
done;
#find most recent file in the current LOG and rename it
filename="$( cat LOG"$n".txt | xargs stat -c '%Y %n' | sort | tail -n1 )";
RUNDATE="$(date -r $filename %Y%b%d)";
a="$(echo $filename | head -c6)";
t="$(( n 3030 ))";
b="$(echo "$a" | sed "s/file$n/T$t/")"
mv "$filename" "${b}-${RUNDATE}.pdf" 2> /dev/null
rm -i LOG$n.txt;
done;
#Coded by the great-taerg 2199 (c) 2021