Просто ищу отзывы и конструктивную критику. Это второй сценарий, который я когда-либо делал. Совсем недавно начал изучать азы. В любом случае просто хотел опубликовать сценарий и посмотреть, не смогу ли я получить какие-то данные о том, где я могу что-то сделать лучше.
Скрипт предназначен для извлечения сжатых типов файлов, с которыми вы чаще всего сталкиваетесь в Linux. Я добавил возможность извлечения в каталог по выбору пользователя, а не просто ограничивать его только рабочим каталогом.
Я чувствую, что у меня слишком много if
/then
заявления, и они могут быть как-то лучше, но я не уверен. И не уверен, правильно ли я реализовал выходы. Некоторые из вас, вероятно, вздрогнут, когда увидят это лол! В любом случае, если вы можете помочь, спасибо.
#!/bin/bash
error() {
echo "For help, type: nzip -h"
}
usage() {
echo "Usage: nzip [FILE]..."
echo "By default file(s) will be extracted to the working directory."
echo
echo "OPTIONS.."
echo
echo "-d, --directory, eg. nzip [file] [-d] [directory]"
echo
echo
}
if [ $# -eq 0 ]
then
error >&2
exit 1
fi
if [ $# -eq 1 ]
then
case $1 in
-h) usage
exit 0
;;
*.7z) 7z e "$1"
;;
*.tar.bz2) tar xjvf "$1"
;;
*.tar.gz) tar xzvf "$1"
;;
*.rar) unrar e "$1"
;;
*.tar) tar xvf "$1"
;;
*.bz2) bunzip2 "$1"
;;
*.tbz) tar xjvf "$1"
;;
*.gz) gunzip "$1"
;;
*.tgz) tar xzvf "$1"
;;
*.jar) unzip "$1"
;;
*.xz) tar xvf "$1"
;;
*.zip) unzip "$1"
;;
*.Z) uncompress "$1"
;;
*) echo "No extraction option for $1" >&2
exit 1
esac
exit 0
fi
if [ $# -eq 3 ] && [ "$2" = "-d" ]
then
case $1 in
*.7z) 7z e "$1" -o"$3"
;;
*.tar.bz2) tar xjvf "$1" -C "$3"
;;
*.tar.gz) tar xzvf "$1" -C "$3"
;;
*.rar) unrar e "$1" "$3"
;;
*.tar) tar xvf "$1" -C "$3"
;;
*.bz2) bunzip2 "$1" -c > "$3"
;;
*.tbz) tar xjvf "$1" -C "$3"
;;
*.gz) gunzip "$1" -c > "$3"
;;
*.tgz) tar xzvf "$1" -C "$3"
;;
*.jar) unzip "$1" -d "$3"
;;
*.xz) tar xvf "$1" -C "$3"
;;
*.zip) unzip "$1" -d "$3"
;;
*.Z) uncompress "$1" -c > "$3"
;;
*) echo "No extraction option for $1" >&2
exit 1
esac
else
error >&2
exit 1
fi
```
2 ответа
Я не уверен, почему у нас #!/bin/bash
— выглядит обычным, портативным #!/bin/sh
здесь было бы хорошо.
Что мне сразу нравится, это хорошая обработка ошибок, использование &2
для сообщений об ошибках и выхода ненулевое значение.
Все tar
команды можно комбинировать, как tar
способен (с -a
), чтобы автоматически идентифицировать любую схему сжатия, которую он обрабатывает.
Поскольку после запуска архиватора нет необходимости продолжать, мы можем заменить процесс оболочки, используя exec
. Например
case $1 in
*.7z) exec 7z e "$1"
;;
Не делайте этого, если мы расширим программу для обработки нескольких входных файлов (см. Ниже).
Если мы сначала возьмем обычное соглашение о флагах, тогда будет проще, когда мы решим, что хотим обрабатывать больше параметров (например, -v
, поэтому мы можем по умолчанию работать в тихом режиме). И мы можем объединить два больших case
создает, всегда передавая каталог, но по умолчанию в текущий рабочий каталог:
destination=.
die() {
printf '%sn' "$@" >&2
exit 1
}
do_extract() {
case $1 in
*.tar.*|*.t[bg]z) tar xaf "$1" -C "$destination"
;;
*.jar|*.zip) unzip "$1" -d "$destination"
;;
# ...
esac
}
while [ $# -ge 1 ]
do
case "$1" in
-d)
[ $# -gt 1 ] || die "Usage: $0 [-d directory] file..."
destination=$2
shift 2
;;
-*)
die "Unrecognised option: $1"
*)
do_extract "$1"
shift
esac
done
Будь осторожен с echo
:
usage() { echo "Usage: nzip [FILE]..." echo "By default file(s) will be extracted to the working directory." echo echo "OPTIONS.." echo echo "-d, --directory, eg. nzip [file] [-d] [directory]" echo echo }
Другие (например, будущие) версии echo
может относиться к этому -d
как обозначение флага.
Я был бы склонен использовать для этого файл:
usage() {
cat <<'END'
Usage: nzip [FILE] [-d DESTINATION]
By default file(s) will be extracted to the working directory.
OPTIONS:
-d destination
END
}
Обратите внимание, что я изменил строку использования, потому что мы поддерживаем только один файл, и -d
и аргумент назначения идут вместе (и неправильно называть его «каталогом», когда это может быть не имя каталога, если мы распаковываем один файл).
Основываясь на отличном ответе Тоби, это предлагает 2 альтернативных способа анализа вариантов.
#!/usr/bin/env bash
readonly PROGRAM=${0##*/}
readonly USAGE=$(cat <<END_USAGE
Usage: $PROGRAM [FILE]...
By default file(s) will be extracted to the working directory.
OPTIONS
-d, --directory, eg. nzip [file] [-d directory]
END_USAGE
)
die() { printf '%sn' "$*" >&2; exit 1; }
error() { die "For help, type: $PROGRAM -h"; }
usage() { echo "$USAGE"; exit 0; }
extract() {
local file=$1 dest=$2
echo "various ways to decompress $file to $dest"
}
# default destination is the current directory
destination="."
############################################################
# parse options
Теперь мы можем использовать встроенный bash getopts
для анализа параметров, но это позволяет только короткие варианты
while getopts :hd: opt; do
case $opt in
h) usage ;;
d) destination=$OPTARG ;;
:) die "Missing option for -$OPTARG" ;;
*) error ;;
esac
done
shift $((OPTIND - 1))
Или используйте внешний getopt
инструмент, чтобы разрешить длинные варианты тоже
tmp=$( getopt -o 'hd:' --long 'help,directory:' -n "$PROGRAM" -- "$@" ) || exit $?
eval set -- "$tmp"
while true; do
case $1 in
'-h'|'--help') usage ;;
'-d'|'--directory')
destination=$2
shift 2
;;
'--')
shift
break
;;
*) die 'Internal error' ;;
esac
done
А потом:
############################################################
# after option parsing
(( $# > 0 )) || usage
for file in "$@"; do
extract "$file" "$destination"
done
спасибо за всю эту прекрасную информацию. Я реализовал большую часть того, что вы предложили. по крайней мере, те части, которые я понял. Мне еще многому нужно научиться. я знаю, что «-eq» равно, означает ли «-ge» больше или равно? а «-gt» просто больше, чем? также не уверен, что делает сдвиг. и почему бы просто не установить destination = $ 2 с самого начала.
— ядерная бомба
Да, вы правильно угадали этих операторов.
man test
или жемужчина [
for the full details (though Bash has its owntest
built-in, soman bash-builtins
is probably what you want; that’s also where to find a description ofshift
).– Toby Speight
The
while [ $# -ge 1 ]
(или простоwhile [ "$@" ]
) цикл сshift
— довольно распространенная идиома для чтения аргументов опций в сценариях оболочки; ожидайте увидеть это довольно часто при работе с оболочкой.— Тоби Спейт