Bash простой скрипт, копирующий файлы в указанную c папку + переименование в сегодняшнюю дату вступления в силу - PullRequest
1 голос
/ 18 марта 2020

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

STUDENT_ACCOUNTS_20200217074343-20200217.xlsx  
STUDENT_MARKS_20200217074343-20200217.xlsx  
STUNDENT_HOMEWORKS_20200217074343-20200217.xlsx  
STUDENT_PHYSICAL_20200217074343-20200217.xlsx  
SUBSCRIBED_STUDENTS_20200217074343-20200217.xlsx

[имя_файла + todaydatetime-todaydate.xlsx]

Но иногда учитель не загружает эти файлы, и нам нужно вручную переименовать файлы, полученные за предыдущую дату, а затем скопировать каждый отдельный файл в отдельную папку, например:

cp STUDENT_ACCOUNTS_20200217074343-20200217.xlsx /incoming/A1/STUDENT_ACCOUNTS_20200318074343-20200318.xlsx  
cp STUDENT_MARKS_20200217074343-20200217.xlsx  /incoming/B1/STUDENT_ACCOUNTS_20200318074343-20200318.xlsx  
.............

cp SUBSCRIBED_STUDENTS_20200217074343-20200217.xlsx /incoming/F1/SUBSCRIBED_STUDENTS_20200318074343-20200318.xlsx.  

In два слова - взятие файлов с предыдущей даты, копирование их в указанную c папку с новой отметкой времени.

#!/bin/bash
cd /home/incoming/
date=$(date '+%Y%m%d')
previousdate="$( date --date=yesterday '+%Y%m%d' )"
cp /home/incoming/SUBSCRIBED_STUDENTS_'$previousdate'.xlsx /incoming/F1/SUBSCRIBED_STUDENTS_'$date'.xlsx  

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

1 Ответ

1 голос
/ 18 марта 2020

Процесс может быть полностью автоматизирован, если известна ваша структура каталогов. Если он следует некоторому шаблону, упомяните его здесь.

Для синхронизации это может быть полезно:

Имя файла "tscp"

#
# Stands for timestamped cp
#
tscp() {

    local file1=$1 ; shift
    local to_dir=$1 ; shift
    local force_copy=$1 ; shift

    local current_date="$(date '+%Y%m%d')"

    if [ "${force_copy}" == "--force" ] ; then
        cp "${file1}" "${to_dir}/$(basename ${file1%-*})-${current_date}.xlsx"
    else
        cp -n "${file1}" "${to_dir}/$( basename ${file1%-*})-${current_date}.xlsx"
    fi
}

tscp "$@"

Используется как следует:

tscp source to_directory [-—force]

В основном сценарий принимает 2 аргумента, а третий необязательный.

Первый аргумент - путь к исходному файлу, а второй - путь к каталогу, куда вы хотите скопировать ( . если тот же каталог).

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

Если вы хотите перезаписать файл назначения, передайте третий arg —force.

Опять же, это можно уточнить гораздо больше, основываясь на предоставленных деталях.

Пример использования на данный момент:

bash tscp SUBSCRIBED_STUDENTS_20200217074343-20200217.xlsx /incoming/F1/

скопирует SUBSCRIBED_STUDENTS_20200217074343-20200217 .xlsx в каталог / входящий / F1 / с обновленной датой, если она еще не существует.

ОБНОВЛЕНИЕ:

Дайте этому go:

#! /usr/bin/env bash

printf_err() {
    ERR_COLOR='\033[0;31m'
    NORMAL_COLOR='\033[0m'
    printf "${ERR_COLOR}$1${NORMAL_COLOR}" ; shift
    printf "${ERR_COLOR}%s${NORMAL_COLOR}\n" "$@" >&2
}

alias printf_err='printf_err "Line ${LINENO}: " '
shopt -s expand_aliases

usage() {

    printf_err \
        "" \
        "usage: ${BASH_SOURCE##*/} " \
        "  -f copy_data_file" \
        "  -d days_before" \
        "  -m months_before" \
        "  -o" \
        "  -y years_before" \
        "  -r " \
        "  -t to_dir" \
            >&2

    exit 1
}

fullpath() {
    local path="$1" ; shift
    local abs_path

    if [ -z "${path}" ] ; then
        printf_err "${BASH_SOURCE}: Line ${LINENO}: param1(path) is empty"
        return 1
    fi

    abs_path="$( cd "$( dirname "${path}" )" ; pwd )/$( basename ${path} )"

    printf "${abs_path}"
}

OVERWRITE=0
REVIEW=0
COPYSCRIPT="$( mktemp "/tmp/copyscriptXXXXX" )"

while getopts 'f:d:m:y:t:or' option
do
    case "${option}" in
        d)
            DAYS="${OPTARG}"
            ;;
        f)
            INPUT_FILE="${OPTARG}"
            ;;
        m)
            MONTHS="${OPTARG}"
            ;;
        t)
            TO_DIR="${OPTARG}"
            ;;
        y)
            YEARS="${OPTARG}"
            ;;
        o)
            OVERWRITE=1
            ;;
        r)
            REVIEW=1
            COPYSCRIPT="copyscript"
            ;;
        *)
            usage
            ;;
    esac
done

INPUT_FILE=${INPUT_FILE:-$1}
TO_DIR=${TO_DIR:-$2}

if [ ! -f "${INPUT_FILE}" ] ; then
    printf_err "No such file ${INPUT_FILE}"
    usage
fi


DAYS="${DAYS:-1}"
MONTHS="${MONTHS:-0}"
YEARS="${YEARS:-0}"

if date -v -1d > /dev/null 2>&1; then
    # BSD date

    previous_date="$( date -v -${DAYS}d -v -${MONTHS}m -v -${YEARS}y '+%Y%m%d' )"

else
    # GNU date

    previous_date="$( date --date="-${DAYS} days -${MONTHS} months -${YEARS} years" '+%Y%m%d' )"

fi

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

tmpfile="$( mktemp "/tmp/dstnamesXXXXX" )"


awk -v to_replace="${previous_date}" -v replaced="${current_date}" '{

    gsub(to_replace, replaced, $0)
    print

}' ${INPUT_FILE} > "${tmpfile}"


paste ${INPUT_FILE} "${tmpfile}" |
    while IFS=$'\t' read -r -a arr
    do
        src=${arr[0]}
        dst=${arr[1]}
        opt=${arr[2]}

        if [ -n "${opt}" ] ; then

            if [ ! -d "${dst}" ] ;
            then
                printf_err "No such directory ${dst}"
                usage
            fi

            dst="${dst}/$( basename "${opt}" )"

        else

            if [ ! -d "${TO_DIR}" ] ; 
            then
                printf_err "No such directory ${TO_DIR}"
                usage
            fi

            dst="${TO_DIR}/$( basename "${dst}" )"
        fi

        src=$( fullpath "${src}" )
        dst=$( fullpath "${dst}" )

        if [ -n "${OVERWRITE}" ] ; then
            echo "cp ${src} ${dst}"
        else
            echo "cp -n ${src} ${dst}"
        fi
    done > "${COPYSCRIPT}"


if [ "${REVIEW}" -eq 0 ] ; then

    ${BASH} "${COPYSCRIPT}"
    rm "${COPYSCRIPT}"

fi

rm "${tmpfile}"

Шаги:

  1. Сохраните вышеуказанный скрипт в файле, скажем `tscp`.
  2. Теперь вам нужно создать входной файл для него. Из вашего примера пример входного файла может выглядеть следующим образом:
    STUDENT_ACCOUNTS_20200217074343-20200217.xlsx         /incoming/A1/
    STUDENT_MARKS_20200217074343-20200217.xlsx         /incoming/B1/
    STUNDENT_HOMEWORKS_20200217074343-20200217.xlsx  
    STUDENT_PHYSICAL_20200217074343-20200217.xlsx  
    SUBSCRIBED_STUDENTS_20200217074343-20200217.xlsx         /incoming/FI/
    

    Где первая часть - это имя исходного файла, а после «вкладки» (это обязательно должна быть вкладка) вы упоминаете каталог назначения. Эти пути должны быть либо абсолютными, либо относительными к каталогу, в котором вы выполняете сценарий.

    Вы не можете упомянуть каталог назначения, если все они должны быть отправлены в один и тот же каталог (обсуждается позже).
    Допустим, вы назвали этот файл `file`.

    Кроме того, вам не обязательно все это печатать. Если у вас есть эти файлы в текущем каталоге, просто сделайте это:
    ls -1 > file
    
    (выше указано ls "one", а не "l".)
  3. Теперь у нас есть `file` сверху, в котором мы не упомянул каталог назначения для всех, но только для некоторых. Допустим, мы хотим переместить все остальные каталоги в `/coming / x`, и он существует.

    Теперь сценарий должен выполняться следующим образом:
    bash tscp -f file -t /incoming/x -r
    
    Где `/ входящий / x` - каталог по умолчанию, т.е. когда в` file` не указан другой каталог, ваши файлы перемещаются в этот каталог.

    Теперь в текущем каталоге будет сгенерирован скрипт с именем `copyscript`, который будет содержать команды` cp` для копирования всех файлов. Вы можете открыть обзор `copyscript` и, если копирование кажется правильным, go впереди и:
    bash copyscript
    
    , который скопирует все файлы, а затем вы можете:
    rm copyscript
    
  4. Вам не нужно генерировать для` copyscript` и может сразу go для копии наподобие:
    bash tscp -f file -t /incoming/x
    
    , которая не будет генерировать какой-либо copyscript и копировать сразу.

    Ранее `-r` вызывал генерацию` copyscript`. Я бы рекомендовал использовать версию с `-r`, потому что это немного безопаснее, и вы будете уверены, что делаются правильные копии.
  5. По умолчанию он будет проверять предыдущий день и переименовывать в текущую дату, но вы можете изменить это поведение следующим образом:
    bash tscp -f file -t /incoming/x -d 3
    
    `-d 3` будет искать файлы за 3 дня в` file`.
  6. По умолчанию копии не перезаписываются, т. Е. Если файл в месте назначения уже существует, копии не будут создаваться. Если вы хотите перезаписать, добавьте флаг `-o`.

В заключение я бы посоветовал использовать:

bash tscp -f file -r

, где file содержит значения, разделенные табуляцией, как указано выше для всех.

Также добавляется tscp в путь было бы хорошей идеей после того, как вы убедились, что он работает нормально.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...