简体   繁体   中英

Looking for an easier shell script for renaming multiple files with multiple patterns

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

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.

NB Once the file formats agree with your requirements, remove the -n option for rename and the files will be renamed.

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
    !/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 $F +%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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM