Я все еще на пути обучения bash, shell, Linux, regex et c. Сегодня я делюсь этим bash сценарием оболочки, который я запрограммировал и который хочу использовать в качестве «модуля» в будущих сценариях. Он тщательно проверяет правильность набора параметров командной строки. Я хотел бы попросить опытных адептов за советом и комментариями о том, как лучше архивировать вещи с точки зрения синтаксиса, различных подходов или альтернативных команд. Было много того, что я пробовал по-другому, но я не мог понять это. Особенно мне не нравятся структуры case. Я бы лучше определил набор букв опций, например, «cmds = (hogam)», а затем l oop через «for c в« $ {cmds [@]} »; делать'. Но это приводит к проблеме, что мне придется использовать динамические c имена переменных, и я не мог понять это. Другая проблема заключается в том, что я могу присвоить логическое значение «истина», но я не могу отрицать его с помощью чего-то вроде «a =! A». Et c. Любые предложения очень приветствуются!
#!/bin/bash
# Usage: -p <path> -g <group> -o <owner> -m <mask> -h (help)
# Extensive option and parameter check:
expecting_option=true # alternatingly expecting option switch and parameter on command line
for i do # loop $i trough all parameters
# display help:
if [ $i = "-h" ]; then
echo "Usage:"
echo "-p <path> (default .)"
echo "-o <owner>"
echo "-g <group>"
echo "-m <permission mask> (000 - 777)"
exit
fi;
if [ "$expecting_option" = true ]; then # next arg supposed to be an option
if [[ "$i" =~ ^(.)(.*?)(.*?)$ ]]; then # retrieve up to 3 single characters
# Does it begin with '-' ?
if [ ${BASH_REMATCH[1]} != "-" ]; then
echo "ERROR: Option to begin with '-' expected at '"$i"'" >&2
exit
fi
# only one letter length for options
if [ -n "${BASH_REMATCH[3]}" ]; then
echo "ERROR: Invalid option '"$i"'. Use -h for help" >&2
exit
fi
switch=${BASH_REMATCH[2]} # save the current option switch
# has this option already been set?
# is option valid?
case $switch in
o) if [ $o ]; then
echo 'ERROR: duplicate option: -o' >&2
exit
fi;;
g) if [ $g ]; then
echo 'ERROR: duplicate option: -g' >&2
exit
fi;;
m) if [ $m ]; then
echo 'ERROR: duplicate option: -m' >&2
exit
fi;;
p) if [ $p ]; then
echo 'ERROR: duplicate option: -p' >&2
exit
fi;;
*) echo "ERROR: Invalid option '"$i"'. Use -h for help" >&2
exit;;
esac
fi
# next arg supposed to be the parameter
expecting_option=!true # it's not true, so it works. But is it 'false'?
else # this is supposed to be a parameter for the previous option switch
if [[ "$i" =~ ^\- ]]; then # starts with '-' ?
echo "ERROR: Parameter for "$switch" missing." >&2
exit
fi
case $switch in
o) # check if designated owner exists (=0):
if ! [ $(id -u "$i" > /dev/null 2>&1; echo $?) -eq 0 ]; then
echo "ERROR: user '"$i"' does not exist." >&2
exit
fi
o="$i";;
g) # check if designated group exists:
if [ -z $(getent group "$i") ]; then
echo "ERROR: group '"$i"' does not exist." >&2
exit
fi
g="$i";;
m) if ! [[ $i =~ ^[0-7][0-7][0-7]$ ]]; then
echo "ERROR: Invalid right mask '"$i"'" >&2
exit
fi
m="$i";;
p) # check if path exists
if ! [ -d "${i}" ]; then
echo "ERROR: Directory '"$i"' not found." >&2
exit
fi
p="$i";;
esac
expecting_option=true
fi
done
# last arg must be a parameter:
if [ "$expecting_option" != true ]; then
echo "ERROR: Parameter for "$switch" missing." >&2
exit
fi
# at least o, g or m must be specified:
if ! [ $g ] && ! [ $o ] && ! [ $m ] ; then
# this didn't work: if ! [ [ $g ] || [ $o ] || [ $m ] ] ; then
echo "Nothing to do. Specify at least owner, group or mask. Use -h for help."
exit
fi
# defaults: path = . owner = no change group = no change mask = no change
# set defaults:
[[ -z $p ]] && p="."
# All necessary options are given and checked:
# p defaults to . otherwise valid path
# if o is given, than the user exists
# if g is given, than the group exists
# if m is given, than the mask is valid
# at least one of o,g or m are given
# no option dupes
# no missing parameters
# ok, now let's do something:
# set group:owner + mask of whole directory tree:
if [ $g ] || [ $o ] ; then
[[ -n $g ]] && g=":"$g # use chown's column only if group change required, with or without owner
sudo find $p -type f -exec chown $o$g {} + &&
sudo find $p -type d -exec chown $o$g {} +
fi
if [ $m ]; then
sudo find $p -type f -exec chmod $m {} + &&
sudo find $p -type d -exec chmod $m {} +
fi