LINUX.ORG.RU

Bash - Резервное копирование файлов, заданных аргументами

 


1

1

Имеется такое задание:

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

Я третий день изучаю bash и набросал очень примитивный код:


#!/bin/bash
mkdir $1 && 
cd $1 && 
tar -czf $1-`date +%F--%H-%M`.tar.gz $2

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

Сейчас держу в уме такой алгоритм: принимать три и более аргументов, где первый аргумент — каталог, куда архивируем, второй аргумент — сколько файлов архивируем, третий и последующие аргументы — файлы, которые архивируем. Далее цикл от 1 до $2 , где в теле архивируются все файлы, заданные аргументами $3 и далее.

Но мне кажется, что этот способ не рационален...

Может, можно как-то проще это реализовать?

Что-нибудь посоветуете

В переменной $# лежит число переданных аргументов, так-то.

devsdc ★★
()

Написанный тобой код сработает только первый раз на каждой директории (каталоге), т.е. если ты вызовешь два раза свой скрипт с указанием одинаковой директории, но указанием разных имён файлов, то второй вызов ничего не сделает. Ибо ты используешь '&&', что заменяет логическое «и» и интерпретатор фактически проверяет результат работы предыдущей команды и лишь если он успешен, то будет запущена следующая команда.

Так что как минимум уберите '&&', просто каждую отдельную команду пишите на отдельной строке.

Кроме всего прочего неплохобы проверять существует директория или нет, а не бездумно пытаться её создавать:

#!/bin/sh
test -d "${1}" || mkdir "${1}"

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

tar -czf "${1}/${1}-`date +%F--%H-%M`.tar.gz" "${2}"

Сейчас держу в уме такой алгоритм: принимать три и более аргументов, где первый аргумент — каталог, куда архивируем, второй аргумент — сколько файлов архивируем, третий и последующие аргументы — файлы, которые архивируем. Далее цикл от 1 до $2 , где в теле архивируются все файлы, заданные аргументами $3 и далее.

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

kostik87 ★★★★★
()

shift - убирает первый аргумент.
$@ - все текущие аргументы. Обязательно в двойных кавычках.
P. S. $0 - имя текущего скрипта

Демонстрация:

#!/bin/bash

echo "$# arguments"
echo $1
shift
echo "$@"
echo "---"
[[ -n "$1" ]] && "$0" "$@"

Запускать скрипт с несколькими аргументами, несколько сделай с пробелами.

BUG: Так можно передавать не только имена файлов, но и параметры к tar.

Kroz ★★★★★
()
Последнее исправление: Kroz (всего исправлений: 1)
Ответ на: комментарий от anonymous

Опередил.
Только "$@" в двойных кавычках должен быть.

Kroz ★★★★★
()
Ответ на: комментарий от vel

mkdir "$D" && cd "$D" && tar -czf "$D-`date +%F--%H-%M`.tar.gz" $*

Должен быть именно "$@" и при этом обязательно в двойных кавычках. $* представляет все аргументы как одно слово. Попробуй подставь $* в мой скрипт вверху и вызови его с аргументами "1 2" "3 4" 5 "6 7" - увидишь в чем ошибка.

Kroz ★★★★★
()
Ответ на: комментарий от Kroz

да, знаю. Но для простых ситуаций достаточно $*

vel ★★★★★
()
Ответ на: комментарий от mystery

Лучше использовать перл или питон

Покажи выполнение задачи ТСа на перле и/или питоне. Согласно алгоритму в шапке + shift (который просто убирает первый аргумент).

Kroz ★★★★★
()
Ответ на: комментарий от Kroz

Покажи выполнение задачи ТСа на перле и/или питоне

#!/usr/bin/python3

import os
import sys
import tarfile
import argparse
from datetime import datetime

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description='Написать командную процедуру, '+
            'которая создает каталог для резервного '+
            'копирования файлов. Имена каталога и '+
            'файлов указываются в виде аргументов.'
    )
    parser.add_argument(
        'dst', metavar='dst', type=str,
        help='Директория назначения')
    parser.add_argument(
        'files', metavar='files', type=str, nargs='+',
        help='Список файлов')

    args = parser.parse_args()

    if not os.path.exists(args.dst):
        os.makedirs(args.dst)

    dt = datetime.now().strftime('%Y%m%d_%H%M%S')
    fname = os.path.join(args.dst, dt+'.tar.gz')

    tar = tarfile.open(fname, "w:gz")
    for name in args.files:
        tar.add(name)
    tar.close()

PS: не mystery

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.