Скрипты
Скрипты
Набор команд можно объединять в отдельные файлы и вызывать этот файл вместо написания всех команд, такая опция нужна для большей модульности.
В Unix-среде принято называть такие файлы скриптами.
Напишем такой script.sh
:
#!/bin/sh
## файл script.sh
echo "Hi there"
Скрипты
Чтобы скрипт можно было исполнять нужно сделать несколько вещей.
Во-первых, в начале скрипта нужно указать два специальных символа (тут правильнее сказать: два байта) she-bang: #!
, а за ним путь к интерпретатору, с помощью которого нужно исполнить этот скрипт.
Без них операционная система не поймёт как выполнить код. А с ними запустит интерпретатор и передаст путь к файлу, который запускаем.
Интерпретатор может быть почти любым, не только shell
.
В примере выше she-bang уже указан, скрипт будет интерпретироваться с помощью /bin/sh
.
Скрипты
Во-вторых, необходимо дать права на исполнения владельцу скрипта, т.е. по-умолчанию пользователю, от которого только что создали скрипт.
chmod u+x script.sh
Теперь скрипт можно исполнить отдельным процессом:
./script.sh
## вывод
Hi there
Скрипты
С помощью оператора &&
можно связать установку прав на исполнения и запуск
скрипта в команду-список, а не разбивать на отдельные вызовы:
chmod u+x script.sh && ./script.sh
## вывод
Hi there
Аргументы в bash-скриптах
В скрипт можно передать аргументы, они будут доступны по именам $1
, $2
, $3
и т.д.; скрипт завершается кодом возврата:
#!/usr/bin/env sh
## script.sh
echo $1
echo $2
echo $3
exit 10 # если код не 0
обязательно даём права на исполнение и передаём аргументы как в обычную программу:
chmod u+x script.sh
./script.sh "why braces?" '$1 $2 $3' three
echo $?
Полезные утилиты при работе с аргументами
Довольно полезной при работе с аргументами оказываеться утилита shift
:
shift n
переименует переменные $N+1
, $N+2
, $N+3
, … на $1
, $2
, $3
, …
Полезные утилиты при работе с аргументами
#!/usr/bin/bash
i=1
while ! [ -z ${1+x} ]
do
echo "Here is arg $i: $1"
shift
i=$((i+1))
done
здесь используем сложную подстановку переменной 1
.
В общем виде подстановка ${var+str}
работает так:
- если переменная
var
не установлена, то подставляется пустая строка''
- если переменная
var
установлена, при этом неважно пустая или нет, то результатом подстановки будет значениеstr
Полезные утилиты при работе с аргументами
Так, условие ! [ -z ${1+x} ]
будет возвращать код возарата 0 (всё ок), если в переменной 1 что-то содержится и только в этом случае, во всех остальных случаях условие будет возвращать код возрата 1
Если переменная 1
не установлена, т.е. нет первого аргумента у этого скрипта, то подстановка строки будет пустая строка ''
и тогда [ -z ${1+x} ]
вернёт код возврата 0
, а ! [ -z ${1+x} ]
соответственно 1.
Пользуемся этим и на каждой итерации работаем с первым аргументом, а в конце вызываем shift
без аргументов, он переименует аргументы $2
, $3
, ...
в $1
, $2
, ...
Таким образом скрипт обойдёт все переданные аргументы и выведет их по одному, добавив префикс Here is arg n:
перед выводом каждого аргумента n
.
getopts
, но их проще рассматривать вместе с конструкциями POSIX shell, поэтому
вернёмся к их рассмотрению позже.
Подробнее о всяких сложных подстановках можно найти прямо в стандарте: Shell and Utilities: Detailed Toc#2.6.2 Parameter Expansion
Скрипты на других языках программирования
Обратите внимание как используется shebang в примерах ниже.
Скрипты можно писать и на awk
и на sed
и на других языках.
Но существуют ограничения: можно вызвать интерпретатор только с одним аргументом.
См. https://unix.stackexchange.com/questions/399690/multiple-arguments-in-shebang
Пример на Python
#!/usr/bin/env python3
import os
import sys
def list_files(directory):
try:
files = os.listdir(directory)
for file in files:
path = os.path.join(directory, file)
if os.path.isfile(path):
size = os.path.getsize(path)
print(f"{file}: {size} bytes")
except FileNotFoundError:
print(f"Directory not found: {directory}")
if __name__ == "__main__":
directory = sys.argv[1] if len(sys.argv) > 1 else '.'
list_files(directory)
Пример на Python
Чтобы запустить
chmod +x list_files.py
а потом
./list_files.py /path/to/directory
Что скрипт делает, если в него не передали аргументы?
Пример на Perl
А вот пример на perl:
#!/usr/bin/perl
use strict;
use warnings;
sub count_lines {
my ($filename) = @_;
open(my $fh, '<', $filename) or die "Cannot open file $filename: $!";
my $count = 0;
$count++ while <$fh>;
close $fh;
return $count;
}
my $file = $ARGV[0] or die "Usage: $0 filename\n";
my $lines = count_lines($file);
print "$file has $lines lines\n";
Пример на Perl
Аналогично нужно дать права на исполнения
chmod +x count_lines.pl
и можно исполнить так
./count_lines.pl filename.txt