Linux shell scripting arguments

Bash Beginner Series #3: Passing Arguments to Bash Scripts

In the third part of the Bash Beginner Series, you’ll learn to pass arguments to a bash shell script. You’ll also learn about special bash shell variables.

Arguments can be useful, especially with Bash!

So far, you have learned how to use variables to make your bash scripts dynamic and generic, so it is responsive to various data and different user input.

In this tutorial, you will learn how you can pass variables to a bash scripts from the command line.

Passing argument to a bash shell script

The following script count_lines.sh will output the total number of lines that exist in whatever file the user enters:

#!/bin/bash echo -n "Please enter a filename: " read filename nlines=$(wc -l < $filename) echo "There are $nlines lines in $filename"

For example, the user can enter the file /etc/passwd and the script will spit out the number of lines as a result:

passing argument to bash shell script

This script works fine; however, there is a much better alternative!

Instead of prompting the user for the filename, we can make the user simply pass the filename as a command line argument while running the script as follows:

The first bash argument (also known as a positional parameter) can be accessed within your bash script using the $1 variable.

So in the count_lines.sh script, you can replace the filename variable with $1 as follows:

Notice that I also got rid of the read and first echo command as they are no longer needed!

Finally, you can run the script and pass any file as an argument:

./count_lines.sh /etc/group There are 73 lines in /etc/group

Passing multiple arguments to a bash shell script

You can pass more than one argument to your bash script. In general, here is the syntax of passing multiple arguments to any bash script:

The second argument will be referenced by the $2 variable, the third argument is referenced by $3 , .. etc.

The $0 variable contains the name of your bash script in case you were wondering!

Now we can edit our count_lines.sh bash script so that it can count the lines of more than one file:

You can now run the script and pass three files as arguments to the bash script:

Passing multiple arguments to bash shell script

As you can see, the script outputs the number of lines of each of the three files; and needless to say that the ordering of the arguments matters, of course.

Getting creative with arguments in Bash shell

Some of them are a bit complicated as they may have long syntax or a long array of options that you can use.

Читайте также:  Show current shell linux

Fortunately, you can use bash arguments to turn a hard command into a pretty easy task!

To demonstrate, take a look at the following find.sh bash script:

#!/bin/bash find / -iname $1 2> /dev/null

It’s a very simple script that yet can prove very useful! You can supply any filename as an argument to the script and it will display the location of your file:

Passing arguments to bash shell scripts

You see how this is now much easier than typing the whole find command! This is a proof that you can use arguments to turn any long complicated command in Linux to a simple bash script.

If you are wondering about the 2> /dev/null , it means that any error message (like file cannot be accessed) won't be displayed on the screen. I suggest reading about stderr redirection in Linux to get more knowledge on this topic.

Bonus Tip: Special variables in Bash shell

Bash has a lot of built-in special variables that are quite handy and are available at your disposal.

The table below highlights the most common special built-in bash variables:

Special Variable Description
$0 The name of the bash script.
$1, $2. $n The bash script arguments.
$$ The process id of the current shell.
$# The total number of arguments passed to the script.
[email protected] The value of all the arguments passed to the script.
$? The exit status of the last executed command.
$! The process id of the last executed command.

To see these special variables in action; take a look at the following variables.sh bash script:

You can now pass any arguments you want and run the script:

Using special variables in bash shell scripts

Alright, this brings us to the end of this chapter. I hope you now realize how powerful and useful bash arguments can be.

Need some practice, download this PDF and practice passing arguments to bash scripts with simple scripting challenges. Their solutions are also included.

Источник

Разбираемся с аргументами в Bash-скриптах

Перевод статьи «Handling Arguments in Bash Scripts».

Создание Bash-скриптов для автоматизации набора команд — первый шаг на пути к созданию инструментов, облегчающих вашу жизнь. Даже простые скрипты, читающиеся сверху вниз и запускающиеся по установленному графику, способны сэкономить вам массу времени. Но рано или поздно наступит момент, когда вы захотите настраивать поведение вашего скрипта на лету: создавать директории с нужными вам именами, загружать файлы из определенных git-репозиториев, указывать IP-адреса или порты и т. п. Вот здесь вам и пригодятся аргументы скриптов.

Позиционные и специальные параметры

Bash предоставляет нам переменные, которые присутствуют в любом написанном нами скрипте. Вот несколько самых полезных:

$1, $2, $3, …: позиционные параметры

Позиционные параметры содержат значения, которые вы указываете при запуске своего скрипта (в командной строке) в качестве аргументов. Рассмотрим пример. Допустим, у вас есть скрипт, запускающийся следующим образом:

Переменная $1 будет содержать значение «200», а переменная $2 — значение «goats».

Читайте также:  Ms sql linux настройка

Я использую позиционные параметры в одном из своих простейших скриптов. Этот скрипт я запускаю на работе практически ежедневно (здесь показываю упрощенный вариант):

!/usr/bin/env bash project_name="$1" mkdir -p "$/" echo "New project '$project_name' created!"

Как видите, я беру позиционную переменную $1 и сохраняю ее значение в настоящей именованной переменной. Но делать так не обязательно. Я мог бы написать

и все равно все бы прекрасно работало.

Тем не менее, я предпочитаю сохранять позиционные параметры в именованные переменные вверху своего скрипта. Таким образом любой читатель моего скрипта сможет быстро понять, что к чему. Разумеется, это не заменяет хорошую документацию и надежную обработку ошибок, но это приятный маленький бонус в плане читаемости. Подобные вещи хоть немножко, но помогают, так что это хорошая практика.

Когда я запускаю скрипт вот так:

он генерирует структуру директорий:

catheter-01 |- CAD |- drawings |- mold |- resources

$0: имя скрипта

В позиционной переменной $0 при вызове скрипта сохраняется его имя. Это особенно полезно для вывода сообщений о том, как нужно использовать этот скрипт.

#!/usr/bin/env bash function usage() < echo "Usage: $0 [options]" > # Error handling omitted (for now) if [[ "$1" == -h ]]; then usage exit 0 fi name="$1" echo "Hello, $!"

Вот что получится при запуске:

$ ./greeting -h Usage: ./greeting [options] $ bash greeting -h Usage: greeting [options] $ ./greeting "Ryan" Hello, Ryan!

$#: число аргументов

Кроме позиционных параметров в Bash есть еще и специальные. Переменная $# хранит количество аргументов, переданных через командную строку. Это очень пригождается в обработке ошибок. Что произойдет, если наш скрипт не получит нужных ему аргументов? Давайте обновим скрипт из предыдущего примера и добавим обработку ошибок.

#!/usr/bin/env bash function usage() < echo "Usage: $0 [options]" > ### Hot new error handling! # We expect one argument. Otherwise tell the user how to # call your script. if [[ "$#" -ne 1 ]]; then usage exit 1 fi if [[ "$1" == -h ]]; then usage exit 0 fi name="$1" echo "Hello, $!"

$?: последний код возврата

Лично я нечасто пользуюсь этим специальным параметром в скриптах, зато интенсивно использую его в командной строке. Многие команды, когда их выполнение проваливается, не выводят никаких сообщений. Они просто ничего не делают. Как же вам узнать, успешно ли отработала команда? Можно вывести значение переменной $? , в которой сохраняется код возврата последней запускавшейся команды.

$ ls test.txt code strudel.py $ echo $? 0 $ ls lamedir ls: cannot access 'lamedir': No such file or directory $ echo $? 2

Вот пример использования в скрипте:

#!/usr/bin/env bash dirname="$1" mkdir "$dirname" # This will fail if the directory exists already if [[ "$?" -ne 0 ]]; then # If the directory is already created, that's fine # just print out a message to alert the user echo "Directory '$dirname' already exists. Not making a new one." fi

$@ and $*: все аргументы

Кажется, именно эти переменные вызывают больше всего сложностей у новичков в Bash — и это понятно! Они работают практически одинаково, но разница в их действии может быть очень существенной в каждой отдельной ситуации.

Читайте также:  Просмотр существующих групп linux

Если вы НЕ берете эти переменные в кавычки, они делают одно и то же: вставляют в указанное место все переданные в скрипт аргументы.

#!/usr/bin/env bash echo "====================" echo "This is dollar star." echo "====================" for arg in $*; do echo "$arg" done echo "====================" echo "This is dollar at." echo "====================" for arg in $@; do echo "$arg" done

При запуске получим следующее:

$ ./arg_printer abba dabba "dooby doo" ==================== This is dollar star. ==================== abba dabba dooby doo ==================== This is dollar at. ==================== abba dabba dooby doo

Обратите внимание на аргумент «dooby doo» . Он был взят в кавычки при передаче, но в результате разбился по пробелу на два разных аргумента. Порой это именно то, что нужно, но очень часто — нет.

Переходим к самому интересному: возьмем переменные в кавычки.

Если взять в кавычки $* , в выводе вы получите все аргументы в одной строке. Аргументы будут разделены пробелами и фактически станут одним аргументом. Причем это не зависит от того, были ли они заключены в кавычки при вводе.

Примечание. На самом деле аргументы разделяются $IFS («внутренним разделителем полей»). Обычно это пробел, но стоит знать, что так бывает не всегда.

#!/usr/bin/env bash echo "====================" echo "This is quoted dollar star." echo "====================" for arg in "$*"; do echo "$arg" done
$ ./arg_printer abba dabba "dooby doo" ==================== This is quoted dollar star. ==================== abba dabba dooby doo

Видите? Один аргумент! Хотите самостоятельно реализовать echo?

$ ./my_echo hello my name is Ryan hello my name is Ryan

А вот когда вы берете в кавычки $@ , Bash выводит все аргументы так, как они были переданы изначально. Это, на мой взгляд, самый полезный функционал, потому что позволяет передавать все аргументы подкомандам, сохраняя при этом пробелы и кавычки и не позволяя автоматическому разделению строк Bash все испортить.

#!/usr/bin/env bash echo "====================" echo "This is quoted dollar at." echo "====================" for arg in "$@"; do echo "$arg" done
$ ./arg_printer abba dabba "dooby doo" ==================== This is quoted dollar at. ==================== abba dabba dooby doo

Вы часто увидите это в скриптах, содержащих множество функций. Традиционно, если у вас много функций, вы делаете последнюю функцию в скрипте функцией main . Она будет обрабатывать все аргументы и содержать организационную логику скрипта. А для запуска функции main обычно последней строчкой скрипта идет main "$@" . Вот так:

#!/usr/bin/env bash function usage() < echo "Usage: $0  [options]" > function bigger() < local first="$1" local second="$2" if [[ "$first" -gt "$second" ]]; then echo "$first" else echo "$second" fi >function main() < if [[ "$#" -ne 2 ]]; then usage exit 1 fi local first="$1" local second="$2" bigger "$first" "$second" >main "$@"

Итоги

Надеюсь, теперь вы начинаете понимать силу кастомизации. Используя скрипты Bash, вы можете автоматизировать выполнение многих задач. А благодаря возможности передачи аргументов при вызове скрипта вы можете автоматически выполнять даже те задачи, логика которых зависит от ситуации!

Источник

Оцените статью
Adblock
detector