Bash: переименование файла с датой и номером версии

Я держу версию своих файлов под контролем, используя такие имена, как «2024-02-12 Work Presentation V.1». Я пытаюсь запустить сценарий bash, который автоматически изменяет его версию (при запуске сценария), поэтому дата обновляется до текущей, а номер версии обновляется. Однако, если имя файла уже существует, версия должна увеличиваться, а не перезаписывать файл.

Изначально у меня была куча операторов if и elif, но сейчас я пытаюсь заставить их работать с case. Я пытаюсь обновить дату.

#!/bin/bash

filename = "$1"
current_date=$(date +'%Y-%m-%d')

# Function to check if a file exists
file_exists() {
    if [ -e "$1" ]; then
        return 0  # File exists
    else
        return 1  # File does not exist
    fi
}

# Function to increment the version number
increment_version() {
    local version_number = "$1"
    local incremented_version=$((version_number + 1))
    echo "$incremented_version"
}

# Check if the filename starts with a date in the format YYYY-MM-DD
case "$filename" in
    [0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]\ *V.[0-9]*)
        echo "Filename starts with a date in the format YYYY-MM-DD."
        echo "Filename contains the current date followed by Versionnumber (V.1, V.2, etc.)."
        # Extract the version number from the filename
        version_number=$(echo "$filename" | grep -oP 'V\.\K\d+')
        
        # Check if a file with the same version number exists
        while file_exists "$filename"; do
            echo "File with version $version_number already exists."
            # Increment the version number
            version_number=$(increment_version "$version_number")
            # Modify the filename with the incremented version number
            filename=$(echo "$filename" | sed "s/V\.[0-9]*/V.$version_number/")
        done

        echo "Creating new file with version $version_number."
        # Copy the original file to the new filename
                        # Add the current date to the start of the filename
            new_filename=$(echo "$filename" | sed 's/^.\{11\}//')
 
            new_filename_with_date = "${current_date} ${new_filename}"
                    
        cp "$1" "$filename"
        echo "$new_filename_with_date"
 
        ;;
   *) [OTHER CASES]

Это правильно echoesnew_filename_with_date, однако если я попытаюсь поставить это в качестве цели копирования, версии больше не будут увеличиваться, чего я не понимаю.

Другие случаи будут включать в себя такие вещи, как, например, если имя файла имеет дату, но не имеет номера версии, и наоборот.

Любая помощь приветствуется!

Спасибо!

Обновлено: я добавил более близкое решение в качестве ответа.

Это длинный вопрос с относительно длинным сценарием. Можете ли вы сузить вопрос: по каким линиям вам нужна помощь? Каковы входные данные (значения переменных) и ожидаемый результат. Еще лучше: предоставьте образцы входных и выходных данных для всей задачи. Вы получите лучшие ответы.

dash-o 18.02.2024 17:01

Экспортируйте свою функцию. export -f function_name

JayCravens 21.02.2024 15:14

Чтобы не уводить весь ваш вопрос в сторону, но почему бы вам просто не использовать существующую систему контроля версий, например Git? Конечно, такие команды, как git diff, не будут очень полезны для двоичных файлов, но они будут гораздо более гибкими, чем необходимость просматривать каталог файлов с одинаковыми именами. (А сообщения о коммитах могут содержать важную информацию, например, почему 2024-02-17 Work Presentation V.3 отличается от 2024-02-16 WorkPresentation V.2.

chepner 21.02.2024 15:15
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
94
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

После долгих поисков

#!/bin/bash

filename = "$1"
current_date=$(date +'%Y-%m-%d')

# Function to check if a file exists
file_exists() {
    if [ -e "$1" ]; then
        return 0  # File exists
    else
        return 1  # File does not exist
    fi
}

# Function to increment the version number
increment_version() {
    local version_number = "$1"
    local incremented_version=$((version_number + 1))
    echo "$incremented_version"
}

# Check if the filename starts with a date in the format YYYY-MM-DD
case "$filename" in
    [0-9][0-9][0-9][0-9]-[0-01][0-9]-[0-3][0-9]\ *V.[0-9]*.md)
        # Extract the version number from the filename
        version_number=$(echo "$filename" | grep -oP 'V\.\K\d+')

        # Increment the version number
        version_number=$(increment_version "$version_number")

        # Remove the old date from the filename
        filename_without_date = "${filename:11}"

        # Modify the filename with the incremented version number
        new_filename = "${current_date} ${filename_without_date%V.*}V.${version_number}"

        # Check if a file with the same version number exists
        while file_exists "$new_filename.md"; do
            echo "File '$new_filename' already exists."
            # Increment the version number
            version_number=$(increment_version "$version_number")
            # Modify the filename with the incremented version number
            new_filename = "${current_date} ${filename_without_date%V.*}V.${version_number}"
        done

        echo "Creating new file with version $version_number."
        
        # Copy the original file to the new filename using rsync
        echo "Copying '$filename' to '$new_filename.md'."
        rsync -a --progress "./$filename" "./$new_filename.md"
        if [ $? -eq 0 ]; then
            echo "File copied successfully."
        else
            echo "Error: Failed to copy file."
        fi
        ;;
    *)
        # If the filename does not start with a date
        echo "Filename does not start with a date."
        # Rename the original file with today's date and the filename
        new_filename = "${current_date} ${filename}"

        # Add a version number to the filename
        version_number=1
        new_filename_with_version = "${new_filename%.*} V.${version_number}"

        # Check if a file with the same filename exists
        while file_exists "$new_filename_with_version.md"; do
            echo "File '$new_filename_with_version' already exists."
            # Increment the version number
            version_number=$(increment_version "$version_number")
            # Modify the filename with the incremented version number
            new_filename_with_version = "${new_filename%.*} V.${version_number}"
        done

        echo "Creating new file with version $version_number."
        
        # Copy the original file to the new filename using rsync
        echo "Copying '$filename' to '$new_filename_with_version.md'."
        rsync -a --progress "./$filename" "./$new_filename_with_version.md"
        if [ $? -eq 0 ]; then
            echo "File copied successfully."
        else
            echo "Error: Failed to copy file."
        fi
        
        # Copy the original file to a new filename with "V.1" suffix
        original_filename_with_version = "${current_date} ${filename%.*} V.${version_number}"
        echo "Copying '$filename' to '$original_filename_with_version.md'."
        rsync -a --progress "./$filename" "./$original_filename_with_version.md"
        if [ $? -eq 0 ]; then
            echo "Original file copied successfully."
        else
            echo "Error: Failed to copy original file."
        fi
        
        # Rename the original file with "V.1" suffix
        echo "Renaming original file to '$original_filename_with_version.md'."
        mv "./$filename" "./$original_filename_with_version.md"
        if [ $? -eq 0 ]; then
            echo "Original file renamed successfully."
        else
            echo "Error: Failed to rename original file."
        fi
        
        # Copy the original file to a new filename with "V.2" suffix
        new_version_number=2
        new_filename_with_version_2 = "${current_date} ${filename%.*} V.${new_version_number}"
        # Check if a file with the same filename exists
        while file_exists "$new_filename_with_version_2.md"; do
            echo "File '$new_filename_with_version_2' already exists."
            # Increment the version number
            new_version_number=$(increment_version "$new_version_number")
            # Modify the filename with the incremented version number
            new_filename_with_version_2 = "${current_date} ${filename%.*} V.${new_version_number}"
        done
        
        echo "Creating new file with version $new_version_number."
        
        # Copy the original file to the new filename with "V.2" suffix using rsync
        echo "Copying '$filename' to '$new_filename_with_version_2.md'."
        rsync -a --progress "./$filename" "./$new_filename_with_version_2.md"
        if [ $? -eq 0 ]; then
            echo "File copied successfully."
        else
            echo "Error: Failed to copy file."
        fi
        ;;
esac

Моя цель — проверить имя файла. оригинал должен быть переименован в имя файла -> 17 февраля 2024 г. имя файла V.1 а затем одновременно скопировал 17 февраля 2024 г. имя файла V.2

последующие итерации должны увеличивать номер версии в конце.

Если указана не дата, а номер версии, сохраните номер версии, но добавьте текущую дату.

Если есть дата, но нет номера версии, добавьте номера версий.

Любая помощь приветствуется!

Ответ принят как подходящий

Хорошо, исходя из ваших требований, этот скрипт должен делать то, что вы хотите:

#!/bin/bash

originalFilename = "$1"
#
# This function returns the highest version number for the given baseName and extension.
latestVer () {
  local baseName = "$1"
  local fileExt = "$2"

  maxVer=$(ls -1 | egrep -e "[0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9] ${baseName} V.[0-9]*${fileExt}" | sed -ne 's/.* V\.\([0-9]*\).*/\1/p' | sort -n | tail -1)
  if [ -z "$maxVer" ]; then
    echo 0
  else
    echo $maxVer
  fi
}

if [ ! -e "$originalFilename" ]; then
  echo "Error, can't access '$originalFilename'." 1>&2
  exit 1
fi
#
# First deconstruct the filename to get the parts.
baseName = "$1"
#
# Check to see if the file already has the date in front.
fileDate=$(echo "$baseName" | sed -ne 's/^\([0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]\) .*/\1/p')
#
# If the filename already has the date, strip it off.
if [ ! -z "$fileDate" ]; then
  baseName=$(echo "$baseName" | sed -ne 's/^[0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9] \(.*\)/\1/p')
fi
#
# Check to see if it has an extension:
#   First check if the only extension is the version number.
fileExt = ""
fileVer=$(echo "$baseName" | sed -ne 's/.*V\.\([0-9]*\)$/\1/p')
if [ -z "$fileVer" ]; then
  fileExt=$(echo "$baseName" | sed -ne 's/.*\(\..*\)$/\1/p')
fi
#
# If it has an extension, strip it off
if [ ! -z "$fileExt" ]; then
  baseName=$(echo "$baseName" | sed -ne 's/\(.*\)\..*$/\1/p')
fi
#
# Check to see if the version number already exist.
fileVer=$(echo "$baseName" | sed -ne 's/.* V\.\([0-9]*\)$/\1/p')
#
# If it has a version number, strip it off
if [ ! -z "$fileVer" ]; then
  baseName=$(echo "$baseName" | sed -ne 's/\(.*\) V\.[0-9]*$/\1/p')
fi

targetFileVer=$(latestVer "$baseName" "$fileExt")
let targetFileVer+=1
#
# Get the current date.
curDate=$(date +'%Y-%m-%d')
#
# If the original filename didn't have a fileDate or a fileVer then this must be the
# first time of it being put into this naming convention. So, move the file to the new
# naming convention, and the next step will copy a new version.
if [ -z "$fileDate" -o -z "$fileVer" ]; then
  #
  # Move the file, while perserving any versioning components that are already there.
  moveFilename = "${fileDate:-$curDate} $baseName V.${fileVer:-$targetFileVer}${fileExt}"
  mv "$originalFilename" "$moveFilename"
  originalFilename = "$moveFilename"
  targetFileVer=$(latestVer "$baseName" "$fileExt")
  let targetFileVer+=1
fi
#
# The new filename should be "<currentDate> <filename> V.<versionNumber>"
targetFilename = "$curDate $baseName V.$targetFileVer${fileExt}"
while [ -e "$targetFilename" ]; do
  let targetFileVer+=1
  targetFilename = "$curDate $baseName V.$targetFileVer${fileExt}"
done

cp "$originalFilename" "$targetFilename"

Тестовый пример 1: Моя цель — проверить имя файла. оригинал должен быть переименован в имя файла -> 2024-02-17 имя файла V.1, а затем одновременно скопирован 2024-02-17 имя файла V.2

clady@clady01-PC:~/junkdir$ touch testfile1
clady@clady01-PC:~/junkdir$ ./addversioninfo testfile1
clady@clady01-PC:~/junkdir$ ll
total 12
drwxr-xr-x  2 clady clady 4096 Feb 21 21:45  ./
drwxr-xr-x 24 clady clady 4096 Feb 21 20:23  ../
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile1 V.1'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile1 V.2'
-rwxr-xr-x  1 clady clady 2645 Feb 21 20:23  addversioninfo*

Тестовый пример 2: Если есть дата, но нет номера версии, добавьте номера версий.

clady@clady01-PC:~/junkdir$ touch "2024-01-01 testfile2"
clady@clady01-PC:~/junkdir$ ./addversioninfo "2024-01-01 testfile2"
clady@clady01-PC:~/junkdir$ ll
total 12
drwxr-xr-x  2 clady clady 4096 Feb 21 21:45  ./
drwxr-xr-x 24 clady clady 4096 Feb 21 20:23  ../
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-01-01 testfile2 V.1'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile1 V.1'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile1 V.2'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile2 V.2'
-rwxr-xr-x  1 clady clady 2645 Feb 21 20:23  addversioninfo*

Тестовый пример 3: Если указана не дата, а номер версии, сохраните номер версии, но добавьте текущую дату.

clady@clady01-PC:~/junkdir$ ./addversioninfo "testfile3 V.9"
clady@clady01-PC:~/junkdir$ ll
total 12
drwxr-xr-x  2 clady clady 4096 Feb 21 21:46  ./
drwxr-xr-x 24 clady clady 4096 Feb 21 20:23  ../
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-01-01 testfile2 V.1'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile1 V.1'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile1 V.2'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile2 V.2'
-rw-r--r--  1 clady clady    0 Feb 21 21:46 '2024-02-21 testfile3 V.10'
-rw-r--r--  1 clady clady    0 Feb 21 21:46 '2024-02-21 testfile3 V.9'
-rwxr-xr-x  1 clady clady 2645 Feb 21 20:23  addversioninfo*

тестовый пример 4: последующие итерации должны увеличивать номер версии в конце.

clady@clady01-PC:~/junkdir$ ./addversioninfo '2024-02-21 testfile3 V.10'
clady@clady01-PC:~/junkdir$ ll
total 12
drwxr-xr-x  2 clady clady 4096 Feb 21 21:47  ./
drwxr-xr-x 24 clady clady 4096 Feb 21 20:23  ../
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-01-01 testfile2 V.1'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile1 V.1'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile1 V.2'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile2 V.2'
-rw-r--r--  1 clady clady    0 Feb 21 21:47 '2024-02-21 testfile3 V.10'
-rw-r--r--  1 clady clady    0 Feb 21 21:47 '2024-02-21 testfile3 V.11'
-rw-r--r--  1 clady clady    0 Feb 21 21:46 '2024-02-21 testfile3 V.9'
-rwxr-xr-x  1 clady clady 2645 Feb 21 20:23  addversioninfo*

тестовый пример 5 Сохранять расширения файлов

clady@clady01-PC:~/junkdir$ touch testfile1.c
clady@clady01-PC:~/junkdir$ ./addversioninfo testfile1.c
clady@clady01-PC:~/junkdir$ ll
total 12
drwxr-xr-x  2 clady clady 4096 Feb 21 21:48  ./
drwxr-xr-x 24 clady clady 4096 Feb 21 20:23  ../
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-01-01 testfile2 V.1'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile1 V.1'
-rw-r--r--  1 clady clady    0 Feb 21 21:48 '2024-02-21 testfile1 V.1.c'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile1 V.2'
-rw-r--r--  1 clady clady    0 Feb 21 21:48 '2024-02-21 testfile1 V.2.c'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile2 V.2'
-rw-r--r--  1 clady clady    0 Feb 21 21:47 '2024-02-21 testfile3 V.10'
-rw-r--r--  1 clady clady    0 Feb 21 21:47 '2024-02-21 testfile3 V.11'
-rw-r--r--  1 clady clady    0 Feb 21 21:46 '2024-02-21 testfile3 V.9'
-rwxr-xr-x  1 clady clady 2645 Feb 21 20:23  addversioninfo*

тестовый пример 6 Увеличение номера версии с расширением

clady@clady01-PC:~/junkdir$ touch  "2024-01-10 abc.md"
clady@clady01-PC:~/junkdir$ ./addversioninfo  "2024-01-10 abc.md"
clady@clady01-PC:~/junkdir$ ll
total 12
drwxr-xr-x  2 clady clady 4096 Feb 21 21:50  ./
drwxr-xr-x 24 clady clady 4096 Feb 21 20:23  ../
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-01-01 testfile2 V.1'
-rw-r--r--  1 clady clady    0 Feb 21 21:50 '2024-01-10 abc V.1.md'
-rw-r--r--  1 clady clady    0 Feb 21 21:50 '2024-02-21 abc V.2.md'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile1 V.1'
-rw-r--r--  1 clady clady    0 Feb 21 21:48 '2024-02-21 testfile1 V.1.c'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile1 V.2'
-rw-r--r--  1 clady clady    0 Feb 21 21:48 '2024-02-21 testfile1 V.2.c'
-rw-r--r--  1 clady clady    0 Feb 21 21:45 '2024-02-21 testfile2 V.2'
-rw-r--r--  1 clady clady    0 Feb 21 21:47 '2024-02-21 testfile3 V.10'
-rw-r--r--  1 clady clady    0 Feb 21 21:47 '2024-02-21 testfile3 V.11'
-rw-r--r--  1 clady clady    0 Feb 21 21:46 '2024-02-21 testfile3 V.9'
-rwxr-xr-x  1 clady clady 2645 Feb 21 20:23  addversioninfo*

тестовый пример 7 В базовом файле есть пробел:

clady@clady01-PC:~/junkdir$ touch "ABC 123 V.3"
clady@clady01-PC:~/junkdir$ ../addversioninfo "ABC 123 V.3"
clady@clady01-PC:~/junkdir$ ll
total 8
drwxr-xr-x  2 clady clady 4096 Feb 29 08:15  ./
drwxr-xr-x 24 clady clady 4096 Feb 29 08:13  ../
-rw-r--r--  1 clady clady    0 Feb 29 08:15 '2024-02-29 ABC 123 V.3'
-rw-r--r--  1 clady clady    0 Feb 29 08:15 '2024-02-29 ABC 123 V.4'

Если вам нравится это решение, проголосуйте за него и отметьте его как принятое.

Я думаю, что это почти правильно, но номера версий идут после расширения файла. Это может испортить мне некоторые вещи. Как бы мне это исправить? Спасибо!!

ReaderGuy42 21.02.2024 11:40

Чтобы мне было понятнее, я обновил сценарий в решении для обработки расширений файлов.

Cloudlady 21.02.2024 15:41

Спасибо! Я отметил это как решение, потому что оно почти идеальное, у меня просто есть еще один случай, который не совсем работает. Если я запустил сценарий на «2024-01-10 abc.md», он превратит это (правильно) в «2024-01-10 abc V.1.md», но тогда копия будет называться «2024-02-21 abc V». .1.md" (т.е. версия копии получает тот же номер). Это поправимо? Спасибо!!

ReaderGuy42 21.02.2024 20:01

Хорошо, сначала было легко исправить один ваш тестовый пример, но затем, тестируя его, я обнаружил другие крайние случаи, в которых, по моему мнению, он не делал то, что вы хотели, поэтому я внес некоторые существенные изменения, но в то же время Я думаю, что сейчас это довольно прочно.

Cloudlady 22.02.2024 04:55

У меня сейчас другая проблема. Не знаю, почему я не понял этого раньше, но если в части basename имени файла есть пробел, это работает неправильно. Затем он меняет дату на текущую, но не увеличивает версию, а просто сбрасывает ее до V.1. Как бы мне это исправить? Спасибо!!

ReaderGuy42 28.02.2024 14:23

Другие вопросы по теме