Проверка параметров для сценария Bash


Я придумал базовый, чтобы помочь автоматизировать процесс удаления ряда папок, поскольку они становятся ненужными.

#!/bin/bash
rm -rf ~/myfolder1//anotherfolder
rm -rf ~/myfolder2//yetanotherfolder
rm -rf ~/myfolder3//thisisafolder

это вызывается так:

./myscript.sh <{id-number}>

проблема в том, что если вы забыли введите id-number(как я сделал), то он может удалить много вещей, которые вы не хотели удалять.

есть ли способ добавить любую форму проверки в командную строку параметры? в моем случае было бы хорошо проверить, что a) есть один параметр, b) он числовой, и c) Эта папка существует; прежде чем продолжить сценарий.

9 84

9 ответов:

#!/bin/sh
die () {
    echo >&2 "$@"
    exit 1
}

[ "$#" -eq 1 ] || die "1 argument required, $# provided"
echo  | grep -E -q '^[0-9]+$' || die "Numeric argument required,  provided"

while read dir 
do
    [ -d "$dir" ] || die "Directory $dir does not exist"
    rm -rf "$dir"
done <<EOF
~/myfolder1//anotherfolder 
~/myfolder2//yetanotherfolder 
~/myfolder3//thisisafolder
EOF

edit: я пропустил часть о проверке, существуют ли каталоги сначала, поэтому я добавил Это, завершив скрипт. Кроме того, были рассмотрены вопросы, поднятые в комментариях; исправлено регулярное выражение, переключенное с == to eq.

это должен быть портативный, совместимый с POSIX скрипт, насколько я могу судить; он не использует никаких башизмов, что на самом деле важно, потому что /bin/sh на Ubuntu на самом деле dash в эти дни, не bash.

The sh решение Brian Campbell, в то время как благородный и хорошо выполненный, имеет несколько проблем, поэтому я подумал, что предоставлю свой собственный bash решение.

проблемы с sh первый:

  • Тильда в ~/foo не распространяется на ваш homedirectory внутри heredocs. И ни тогда, когда его читает read заявление или цитата в rm заявление. Что означает, что вы получите No such file or directory ошибки.
  • разветвление от grep и такие для основных операции-это безумие. Особенно, когда вы используете дерьмовую оболочку, чтобы избежать "тяжелого" веса bash.
  • я также заметил несколько проблем с цитированием, например, вокруг расширения параметра в его echo.
  • в то время как редко, решение не может справиться с именами файлов, которые содержат новые строки. (Почти нет решения в sh может с ними справиться - именно поэтому я почти всегда предпочитаю bash, это гораздо более пуленепробиваемый и труднее использовать при использовании ну.)

в то время как, да, используя /bin/sh для вашего hashbang означает, что вы должны избегать bashisms любой ценой, вы можете использовать все bashизмы вам нравятся, даже на Убунуту или еще что-то, когда вы честны и ставите #!/bin/bash в верхней части.

так вот bash решение, которое меньше, чище, прозрачнее, вероятно, "быстрее" и более пуленепробиваемое.

[[ -d  &&  != *[^0-9]* ]] || { echo "Invalid input." >&2; exit 1; }
rm -rf ~/foo/""/bar ...
  1. обратите внимание на кавычки на rm заявление!
  2. The -d проверка также не удастся, если пусто, так что это две проверки в одном.
  3. я избегал регулярных выражений по какой-то причине. Если вы должны использовать =~ в bash вы должны поместить регулярное выражение в переменную. В любом случае, такие глобусы, как мой, всегда предпочтительны и поддерживаются в гораздо большем количестве версий bash.

Я бы использовал Баш [[:

if [[ ! ("$#" == 1 &&  =~ ^[0-9]+$ && -d ) ]]; then 
    echo 'Please pass a number that corresponds to a directory'
    exit 1
fi

нашел этот faq чтобы быть хорошим источником информации.

Не такой пуленепробиваемый, как приведенный выше ответ, однако все еще эффективный:

#!/bin/bash
if [ "" = "" ]
then
  echo "Usage:  <id number to be cleaned up>"
  exit
fi

# rm commands go here

использовать set -u что приведет к тому, что любая ссылка на незаданный аргумент немедленно завершит работу скрипта.

http://www.davidpashley.com/articles/writing-robust-shell-scripts.html

использовать '-З' для проверки на пустые строки и '-D, чтобы проверить по справочникам.

if [[ -z "$@" ]]; then
    echo >&2 "You must supply an argument!"
    exit 1
elif [[ ! -d "$@" ]]; then
    echo >&2 "$@ is not a valid directory!"
    exit 1
fi

man-страница для теста (man test) предоставляет все доступные операторы, которые можно использовать в качестве логических операторов в bash. Используйте эти флаги в начале вашего скрипта (или функций) для проверки ввода так же, как и на любом другом языке программирования. Например:

if [ -z  ] ; then
  echo "First parameter needed!" && exit 1;
fi

if [ -z  ] ; then
  echo "Second parameter needed!" && exit 2;
fi

вы можете проверить точки A и b компактно, выполнив что-то вроде следующего:

#!/bin/sh
MYVAL=$(echo  | awk '/^[0-9]+$/')
MYVAL=${MYVAL:?"Usage - testparms <number>"}
echo ${MYVAL}

что дает нам ...

$ ./testparams.sh 
Usage - testparms <number>

$ ./testparams.sh 1234
1234

$ ./testparams.sh abcd
Usage - testparms <number>

этот метод должен отлично работать в sh.

старый пост, но я решил, что могу внести свой вклад в любом случае.

сценарий, возможно, не нужен и с некоторым допуском к диким картам может быть выполнен из командной строки.

  1. дикие везде соответствующие. Позволяет удалить любое появление под "папка"

    $ rm -rf ~/*/folder/*
    
  2. оболочке повторяемых. Позволяет удалить определенные папки pre и post с одним линия

    $ rm -rf ~/foo{1,2,3}/folder/{ab,cd,ef}
    
  3. оболочка повторяется + var (bash tested).

    $ var=bar rm -rf ~/foo{1,2,3}/${var}/{ab,cd,ef}