Проверка параметров на Bash script
Я придумал базовый, чтобы помочь автоматизировать процесс удаления нескольких папок, поскольку они становятся ненужными.
#!/bin/bash
rm -rf ~/myfolder1/$1/anotherfolder
rm -rf ~/myfolder2/$1/yetanotherfolder
rm -rf ~/myfolder3/$1/thisisafolder
Это вызвано так:
./myscript.sh <{id-number}>
Проблема заключается в том, что если вы забудете ввести id-number
(как я тогда сделал), он может потенциально удалить много вещей, которые вы действительно не хотите удалять.
Есть ли способ добавить любую форму проверки в параметры командной строки? В моем случае было бы хорошо проверить, что a) есть один параметр, b) он численный, и c) эта папка существует; прежде чем продолжить с script.
Ответы
Ответ 1
#!/bin/sh
die () {
echo >&2 "[email protected]"
exit 1
}
[ "$#" -eq 1 ] || die "1 argument required, $# provided"
echo $1 | grep -E -q '^[0-9]+$' || die "Numeric argument required, $1 provided"
while read dir
do
[ -d "$dir" ] || die "Directory $dir does not exist"
rm -rf "$dir"
done <<EOF
~/myfolder1/$1/anotherfolder
~/myfolder2/$1/yetanotherfolder
~/myfolder3/$1/thisisafolder
EOF
edit. Я пропустил часть проверки, если сначала существуют каталоги, поэтому я добавил это, заполнив script. Кроме того, рассмотрели вопросы, поднятые в комментариях; исправлено регулярное выражение, переключено с ==
на eq
.
Это должен быть портативный POSIX-совместимый script, насколько я могу судить; он не использует никаких базизмов, что на самом деле важно, потому что /bin/sh
на Ubuntu на самом деле dash
в эти дни, а не bash
.
Ответ 2
Решение sh
от Brian Campbell
, хотя оно благородно и хорошо выполнено, имеет несколько проблем, поэтому я решил предоставить свое собственное решение bash
.
Проблемы с sh
one:
- Тильда в
~/foo
не распространяется на ваш родной каталог внутри heredocs. И ни когда он не читается оператором read
или не указан в инструкции rm
. Это означает, что вы получите ошибки No such file or directory
.
- Выключение
grep
, а для основных операций - глупое. Особенно, когда вы используете дерьмовую оболочку, чтобы избежать "тяжелого" веса bash.
- Я также заметил несколько цитат, например, вокруг расширения параметра в его
echo
.
- Редко, решение не может справиться с именами файлов, которые содержат символы новой строки. (Практически никакое решение в
sh
не может справиться с ними - вот почему я почти всегда предпочитаю bash
, он гораздо более пуленепробиваемый и более трудный для использования при его использовании).
Хотя, используя /bin/sh
для вашего хеш-бэнга, вы должны избегать bash
isms любой ценой, вы можете использовать все теги bash
, которые вам нравятся, даже на Ubunutu или еще что-то, когда вы честны и ставите #!/bin/bash
вверху.
Итак, вот решение bash
, которое меньше, чище, более прозрачно, возможно, "быстрее" и более пуленепробиваемо.
[[ -d $1 && $1 != *[^0-9]* ]] || { echo "Invalid input." >&2; exit 1; }
rm -rf ~/foo/"$1"/bar ...
- Обратите внимание на цитаты вокруг
$1
в инструкции rm
!
- Проверка
-d
также завершится с ошибкой, если $1
пуст, поэтому две проверки в одном.
- Я избегал регулярных выражений по какой-то причине. Если вы должны использовать
=~
в bash, вы должны поместить регулярное выражение в переменную. В любом случае, globs, подобные моим, всегда предпочтительнее и поддерживается в гораздо более bash версиях.
Ответ 3
Я бы использовал bash [[
:
if [[ ! ("$#" == 1 && $1 =~ ^[0-9]+$ && -d $1) ]]; then
echo 'Please pass a number that corresponds to a directory'
exit 1
fi
Я нашел этот faq, чтобы быть хорошим источником информации.
Ответ 4
Не как пуленепробиваемый, как вышеприведенный ответ, но все же эффективный:
#!/bin/bash
if [ "$1" = "" ]
then
echo "Usage: $0 <id number to be cleaned up>"
exit
fi
# rm commands go here
Ответ 5
Используйте '-z' для проверки пустых строк и '-d для проверки каталогов.
if [[ -z "[email protected]" ]]; then
echo >&2 "You must supply an argument!"
exit 1
elif [[ ! -d "[email protected]" ]]; then
echo >&2 "[email protected] is not a valid directory!"
exit 1
fi
Ответ 6
Используйте set -u
, который приведет к немедленному сбою любой ссылки на отмененный аргумент. <. w370 > .
http://www.davidpashley.com/articles/writing-robust-shell-scripts.html
Ответ 7
Страница man для теста (man test
) предоставляет все доступные операторы, которые вы можете использовать в качестве логических операторов в bash. Используйте эти флаги в начале ваших script (или функций) для проверки ввода так же, как и на любом другом языке программирования. Например:
if [ -z $1 ] ; then
echo "First parameter needed!" && exit 1;
fi
if [ -z $2 ] ; then
echo "Second parameter needed!" && exit 2;
fi
Ответ 8
Вы можете точно проверить точки a и b, выполнив следующие действия:
#!/bin/sh
MYVAL=$(echo ${1} | 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.
Ответ 9
Старый пост, но я решил, что могу в любом случае внести свой вклад.
A script, возможно, не требуется, и с некоторой допустимостью к диким картам можно было бы выполнить из командной строки.
-
дикий везде соответствующий. Позволяет удалить любое появление подпапки
$ rm -rf ~/*/folder/*
-
Итерация оболочки. Позволяет удалить конкретные пре и почтовые папки с одной строкой
$ rm -rf ~/foo{1,2,3}/folder/{ab,cd,ef}
-
Оболочка с итерацией + var (BASH).
$ var=bar rm -rf ~/foo{1,2,3}/${var}/{ab,cd,ef}