Выбрать главу

№ 16. Работа с архивом удаленных файлов

Теперь, когда в домашней папке пользователя появился скрытый каталог с удаленными файлами, пригодился бы сценарий, позволяющий выбирать для восстановления одну из нескольких удаленных версий. Однако эта задача сложна тем, что нам придется предусмотреть все вероятные проблемы: от невозможности найти требуемый файл до обнаружения нескольких копий, соответствующих заданному критерию. Например, если обнаружится несколько совпадений, какую копию должен восстановить сценарий — самую старую или самую новую? Или он должен вывести сообщение об ошибке, указав в нем количество найденных совпадений? Или вывести список версий и предложить пользователю выбрать нужную? Давайте посмотрим, как решаются эти проблемы на практике, изучив сценарий 2.7, в котором приводится сценарий командной оболочки unrm.

Код

Листинг 2.7. Сценарий unrm для восстановления файлов из резервных копий

··#!/bin/bash

··# unrm — отыскивает в архиве удаленных файлов требуемый файл или

··#·· каталог. Если найдено более одного совпадения, выводит список

··#·· результатов поиска, упорядоченных по времени, и предлагает

··#·· пользователю выбрать нужный для восстановления.

··archivedir="$HOME/.deleted-files"

··realrm="$(which rm)"

··move="$(which mv)"

··dest=$(pwd)

··if [! -d $archivedir]; then

····echo "$0: No deleted files directory: nothing to unrm" >&2

····exit 1

··fi

··cd $archivedir

··# Если сценарий запущен без аргументов, просто вывести список

··#·· удаленных файлов.

··if [$# −eq 0]; then

····echo "Contents of your deleted files archive (sorted by date):"

····ls −FC | sed −e 's/\([[: digit: ]][[: digit: ]]\.\)\{5\}//g' \

······-e 's/^/ /’

····exit 0

··fi

··# Иначе принять шаблон для поиска, предложенный пользователем.

··#·· Проверить наличие в архиве нескольких совпадений с шаблоном

··matches="$(ls −d *"$1" 2> /dev/null | wc −l)"

··if [$matches −eq 0]; then

····echo "No match for \"$1\" in the deleted file archive." >&2

····exit 1

··fi

··if [$matches −gt 1]; then

····echo "More than one file or directory match in the archive: "

····index=1

····for name in $(ls −td *"$1")

····do

······datetime="$(echo $name | cut −c1-14 | \

········awk−F. '{ print $5"/"$4" at "$3":"$2":"$1 }')"

······filename="$(echo $name | cut −c16-)"

······if [-d $name]; then

········filecount="$(ls $name | wc −l | sed 's/[^[: digit: ]]//g')"

········echo " $index) $filename (contents = ${filecount} items," \

············ " deleted = $datetime)"

······else

········size="$(ls −sdk1 $name | awk '{print $1}')"

········echo " $index) $filename (size = ${size}Kb, deleted = $datetime)"

······fi

······index=$(($index + 1))

····done

····echo ""

····/bin/echo −n "Which version of $1 should I restore ('0' to quit)? [1]: "

····read desired

····if [! -z "$(echo $desired | sed 's/[[: digit: ]]//g')"]; then

······echo "$0: Restore canceled by user: invalid input." >&2

······exit 1

····fi

····if [${desired:=1} −ge $index]; then

······echo "$0: Restore canceled by user: index value too big." >&2

······exit 1

····fi

····if [$desired −lt 1]; then

······echo "$0: Restore canceled by user." >&2

······exit 1

····fi

····restore="$(ls −td1 *"$1" | sed −n "${desired}p")"

····if [-e "$dest/$1"]; then

······echo "\"$1\" already exists in this directory. Cannot overwrite." >&2

······exit 1

····fi

····/bin/echo −n "Restoring file \"$1\"…"

····$move "$restore" "$dest/$1"

····echo "done."

····/bin/echo −n "Delete the additional copies of this file? [y] "