Ищете более простой сценарий оболочки для переименования нескольких файлов с несколькими шаблонами

#linux #sed #rename #script #mv

#linux #sed #переименовать #сценарий #mv

Вопрос:

У меня есть куча файлов с этим соглашением об именовании:

 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
 

У меня есть скрипт, который находит самый последний номер каждого файла ( file01 file03 ) и переименовывает его в T3031 , T3032 , T3033 , отсекает все после первых 6 символов и добавляет дату последнего изменения файла. В итоге они выглядят так (это именно то, что я хочу):

 T3031-2018Oct06.pdf
T3032-2019Sep20.pdf
T3033-2017Nov22.pdf
 

Просто сценарий кажется мне длинным и уродливым (для — есть 17 циклов file01 file17 ). Я надеюсь, что у кого-то есть более элегантное решение.

Вот часть того, что у меня есть:

 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
 

Я новичок в написании сценариев, и это мой первый (также новичок в StackOverflow).
Заранее спасибо

Ответ №1:

Это может сработать для вас (сортировка и переименование GNU):

 ls -1 file* |
sort -t_ -k1,1 -k2,2r file1 |
sort -ut_ -k1,1 |
rename -n 'm/^[^_]*(dd)_(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]'
 

Перечислите необходимые file файлы.

Отсортируйте список по номеру файла и обратному порядку дат.

Удалите все, кроме первого номера каждого файла.

Используется rename для форматирования имен файлов.

Примечание. Как только форматы файлов соответствуют вашим требованиям, удалите -n опцию для rename , и файлы будут переименованы.

Ответ №2:

Прежде всего, не анализируйте вывод ls

Цикл оболочки:

 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
 

Или с помощью rename команды (удалите -n опцию, если она выглядит правильно)

 rename -MPOSIX=strftime -n '
    s{file(d ).*}{
        sprintf "T%d-%s.pdf", 3030   $1, strftime("%Y%b%d", localtime((stat)[9]))
    }e
' file*pdf