Unix Если файл существует, переименуйте - PullRequest
0 голосов
/ 19 марта 2012

Я работаю над задачей UNIX, где я хочу проверить, есть ли определенный файл журнала в каталоге или нет. Если он присутствует, я бы хотел переименовать его, добавив отметку времени в конце. Формат имени файла таков: ServiceFileName_0.log

Это то, что у меня есть, но оно не будет переименовано при запуске скрипта, даже если есть файл с именем ServiceFileName_0.log.

renameLogs()
{
   #If a ServiceFileName log exists, rename it

   if [ -f $MY_DIR/logs/ServiceFileName_0.log ]; 
   then
    mv ServiceFileName_0.log ServiceFileName_0.log.%M%H%S
   fi
}

Пожалуйста, помогите!

Спасибо

Ответы [ 4 ]

3 голосов
/ 19 марта 2012

Возможно, вам понадобится префикс имени файла с путем $MY_DIR, как вы это делали в тесте.

1 голос
/ 19 марта 2012
renameLogs()
{
    if [ -f $MY_DIR/logs/ServiceFileName_0.log ] 
    then mv $MY_DIR/ServiceFileName_0.log $MY_DIR/ServiceFileName_0.log.$(date +%M%H%S)
    fi
}

Используйте префикс каталога последовательно.Также вам нужно правильно указать время, как показано на рисунке.

Лучше, хотя (меньше повторений):

renameLogs()
{
    logfile="$MY_DIR/logs/ServiceFileName_0.log"
    if [ -f "$logfile" ] 
    then mv "$logfile" "$logfile.$(date +%H%M%S)"
    fi
}

Примечание: я переставил формат с MMHHSS на более обычный HHMMSSпорядок.Если вы также работаете с компонентами даты, вам следует серьезно рассмотреть возможность использования порядка, рекомендованного ISO 8601, который равен [ГГГГ] ммдд.Он объединяет все файлы журнала за месяц в список ls, что обычно полезно.Использование порядка ddmm означает, что файлы первого числа каждого месяца группируются вместе, а затем файлы второго числа каждого месяца и т. Д. Обычно это менее желательно.

0 голосов
/ 20 марта 2012

Это не ваша очевидная непосредственная проблема, но конструкция if неверна: она вводит время проверки для состояния гонки по времени использования . В промежутке между проверкой if [ -f и mv может возникнуть какой-то другой процесс и что-то изменить, чтобы вы больше не могли перемещать файл, даже если проверка прошла успешно.

Чтобы избежать этого класса ошибок, всегда пишите код, который запускает , пытаясь выполнить операцию, которую вы хотите выполнить, а затем, если она не удалась, выясните, почему. В этом случае вам ничего не нужно делать, если исходный файл не существует, но сообщать об ошибке, если операция не удалась по какой-либо другой причине. Нет хорошего способа сделать это в портативной оболочке, вам нужно что-то, что позволит вам проверить errno. Я, вероятно, написал бы этот помощник C:

#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(int argc, char **argv)
{
    if (argc != 3) {
        fprintf(stderr, "usage: %s source destination\n", argv[0]);
        return 2;
    }
    if (rename(argv[1], argv[2]) && errno != ENOENT) {
        fprintf(stderr, "rename '%s' to '%s': %s\n", 
                argv[1], argv[2], strerror(errno));
        return 1;
    }
    return 0;
}

, а затем используйте его так:

renameLogs()
{
    ( cd "$MY_DIR/logs"
      rename_if_exists ServiceFileName_0.log ServiceFileName_0.log.$(date +%M%H%S)
    )
}

Конструкция ( cd решает вашу непосредственную проблему и, в отличие от других предложений, избегает другой гонки , в которой возникает какой-то другой процесс, и портится в каталоге logs или его родительских каталогах.

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

0 голосов
/ 19 марта 2012

Вы можете заменить это:

mv ServiceFileName_0.log ServiceFileName_0.log.%M%H%S

на это

mv $MY_DIR/logs/ServiceFileName_0.log $MY_DIR/logs/ServiceFileName_0.log.%M%H%S
...