······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] "
····read answer
····if [${answer:=y} = "y"]; then
······$realrm −rf *"$1"
······echo "Deleted."
····else
······echo "Additional copies retained."
····fi
··else
····if [-e "$dest/$1"]; then
······echo "\"$1\" already exists in this directory. Cannot overwrite." >&2
······exit 1
····fi
····restore="$(ls −d *"$1")"
····/bin/echo −n "Restoring file \"$1\"… "
····$move "$restore" "$dest/$1"
····echo "Done."
··fi
··exit 0
Первый фрагмент кода в
, блок в условной инструкции if [$# −eq 0], выполняется, если сценарий запущен без аргументов. Он выводит содержимое архива удаленных файлов. Однако тут есть одна загвоздка: нам нужно вывести имена файлов без префикса со временем удаления, потому что он предназначен только для внутреннего использования. Префикс только ухудшил бы читаемость списка. Для решения этой задачи применяется команда sed в
, которая удаляет первые пять вхождений шаблона «цифра цифра точка» из каждой строки в выводе команды ls.
Пользователь может указать в аргументе имя файла или каталога для восстановления. Следующий шаг в
— проверка количества совпадений с именем, указанным пользователем.
Необычное применение вложенных двойных кавычек в этой строке (вокруг $1) позволяет команде ls находить совпадения с именами файлов, содержащими пробелы, а шаблонный символ * разрешает совпадения с именами, включающими произвольные префиксы с временем удаления. Последовательность 2> /dev/null нужна, чтобы скрыть любые сообщения об ошибках от пользователя, выводимые командой. С наибольшей вероятностью будет скрыто сообщение об ошибке «No such file or directory» («Нет такого файла или каталога»), которое выводит команда ls, когда не может найти файл с указанным именем.
При наличии нескольких совпадений с указанным именем файла или каталога выполняется самая сложная часть сценария — блок в инструкции if [$matches −gt 1]
, который выводит все результаты. Флаг −t в команде ls, вызываемой в главном цикле for, обеспечивает перебор файлов в архиве в обратном хронологическом порядке — от более новых к более старым, а вызов команды awk в
преобразует префикс в имени файла в дату и время удаления в круглых скобках. В строке
определяется размер файла в килобайтах, для чего вызывается команда ls с флагом −k.
Вместо размера записи, соответствующей каталогу в структуре файловой системы, сценарий выводит более полезную информацию — количество файлов в каждом совпавшем каталоге. Вычисляется оно очень просто. В
просто подсчитывается количество строк в выводе команды ls и отбрасываются любые пробелы из вывода команды wc.
Когда пользователь выберет одно из совпадений, команда в
получит точное имя файла для восстановления. Эта команда чуть иначе использует sed. Здесь с помощью флага −n строчному редактору sed передается номер строки (${desired}) и команда p (print — печать), что позволяет быстро извлечь из потока ввода указанную строку. Хотите увидеть только строку с номером 37? Команда sed −n 37p сделает это.
Читать дальше