ДЗ * 0.7 + КР * 0.3
Состоит из:
sh, ash, bash, dash, ksh, zsh...
csh, tcsh
es (functional), psh (Perl), pysh (Python)
Особенности:
$ echo 'Hello, World!'
Hello, World!
pwd вывести текущую директорию
(print working directory)
ls вывести содержимое директории
(list directory content)
cd путь войти в директорию
(change directory)
Абсолютные:
/Users/misha/Documents/work
Начинаются с символа "/"
Относительные:
Documents/work
Относительно текущей директории
/ корневая директория
. текущая директория
.. директория на уровень выше
~ домашняя директория
Tab показать возможные варианты
Tab + Tab выбрать первый вариант (?)
Общий вид команды:
команда опции аргументы
Например:
ls --all --human-readable -l путь
ls -a -h -l путь
ls -ahl путь ls -lah путь
man команда
справка о команде (для выхода: Q)
apropos слово
поиск команды по ключевому слову
whereis команда
показать путь до утилиты
mkdir путь_до_директории
создать директорию
mkdir -p путь_до_директории
создать директорию и ее "родителей"
touch путь_до_файла
создать файл
rm путь_до_файла
удалить файл
rm -r путь_до_директории
удалить директорию
rm -rf путь_до_директории
удалить директорию (без вопросов)
cp путь_до_файла1 путь_до_файла2
скопировать файл1 в файл2
cp -r путь_до_дир1 путь_до_дир2
удалить дир1 в дир2
mv путь1 путь2
переместить директорию или файл
Расширения не важны для ОС!
Тип файла можно определить по метаданным.
file путь определить тип файла
$ file my.txt
my.txt: ASCII text
$ mv my.txt my.jpg
$ file my.jpg
my.jpg: ASCII text
В Unix названия зависят от регистра
(в отличие от Windows).
$ ls Documents
FILE1.txt File1.txt file1.TXT
...
$ file file1.txt
file1.txt: ERROR: cannot open 'file1.txt' (No such file or directory)
Пробел - разделитель аргументов
$ ls -1 Documents
Holiday Photos
...
$ cd Holiday Photos
cd: no such file or directory: Holiday
$ cd 'Holiday Photos'
$ pwd
/Users/misha/Holiday Photos
Текст внутри кавычек разпознается как атомарный аргумент:
В shell есть 2 вида кавычек: '...' и "...".
О их различия - позже.
Используйте '\' для экранирования:
$ cd Holiday\ Photos
$ pwd
/Users/misha/Holiday Photos
При автодополнении shell добавит '\' перед пробелами за вас!
Если имя файла начинается с '.', файл считается скрытым.
$ ls Documents
file1.txt
...
$ ls -a Documents
. .. file1.txt .hidden .file2.txt
cat путь_до_файла
вывести содержимое файла на экран
less путь_до_файла
открыть файл на чтение
q - выход; / - поиск;
g - в начало; G - в конец
nano путь_до_файла
редактировать файл
Ctrl + X - выход
head -n число файл
вывести первые строки файла
tail -n число файл
вывести последние строки файла
wc файл
подсчет слов, строк, символов и байт
wc -l файл
подсчет строк
wc -wc файл
подсчет слов и байт
программа < файл
брать stdin из файла
программа 1> файл
выводить stdout в файл
программа > файл
аналогично (по-умолчанию 1)
программа >> файл
аналогично, но с дозаписью в файл
программа 2> файл
выводить stderr в файл
программа >файл1 2>файл2
перенаправление в один файл
программа &> (или &>>) файл
перенаправление в один файл
программа 2>&1
перенаправление stderr в stdout
программа 2<&1
перенаправление stdout в stderr
/dev/null "черная дыра"
/dev/zero 0-байты
/dev/urandom случайные байты
program 2> /dev/null
игнорировать ошибки
head -c число /dev/zero > файл
создать файл и заполнить его нулями
Прогр1 | Прогр2 | ... | ПрогрN
передать stdin Прогр1 в качестве stdin для Прогр2, далее stdout Прогр2 в качестве stdin для Прогр2 и т.д.
Пример: запуск интерпретатора Python
$ python
>>> 1 + 1
2
>>> 2 + 2
4
>>> # Как завершить работу?
$ python
>>> 1 + 1
2
>>> <EOF> # ^D
^D отправляет на вход EOF (end-of-line),
т.е. сообщает, что ввод окончен
$ python
>>> 1 + 1
2
>>> # ^C
KeyboardInterrupt
^C прерывает текущий процесс
$ python
>>> 1 + 1
2
>>> # ^Z
[1]+ Stopped python
^Z остановить процесс
$ fg
python
1 + 1
2
>>>
fg продолжить выполнение остановленной задачи в интерактивном режиме
$ bg
[1]+ python &
bg продолжить выполнение остановленной задачи в фоновом режиме
fg и bg принимают номер задания. При вызове без параметров применяются к последнему заданию.
$ jobs
[1]- Stopped cmd1
[2]+ Running cmd2 &
jobs показать запущенные задания
$ cmd &
[3] 24128
Можно сразу запустить команду в фоновом режиме (вместо использования ^Z и bg)
stop остановить фоновое задание
wait дождаться завершения задания
вернуть его код возврата
sort сортирует файлы по строкам
Некоторые опции:
-r | выводить в обратном порядке |
-n | сортировать как числа |
-u | только уникальные строки |
-f | игнорировать регистр |
uniq фильтрует повторяющиеся строки
Некоторые опции:
-c | перед каждой строкой выводить число дубликатов |
-d | только повторяющиеся строки |
-u | только строки без дубликатов |
-i | игнорировать регистр |
fold
разбивает длинные строки на несколько
Некоторые опции:
-w <n> | максимальная длина строка |
tr <src> <dst>
мапает символы из входной строки
Некоторые опции:
-c | инвертирует <src> |
-d | удаляет символы из <src> |
$ echo "The quick brown fox \
jumps over the lazy dog" \
| tr -dc A-Za-z \
| tr A-Z a-z \
| fold -w1 \
| sort -u \
| wc -l
26
Простой скрипт hello_world.sh:
#!/bin/bash
echo 'Hello, World!'
#!cmd shebang, указание интерпретатору,
как запускать скрипт
$ bash hello_world.sh
Можно обойтись без shebang:
$ ./hello_world.sh
bash: ./hello_world.sh: Permission denied
Сделать файл исполняемым:
$ chmod +x hello_world.sh
$ ./hello_world.sh
Hello, World!
Переменная (variable)
именованная область памяти
Имя (name):
Значение (value):
Запись (перезапись) значения:
<имя>=<значение>
Чтение:
$<имя> или ${<имя>}
path=~/
path2=$path/file.txt # path2=~/Docs/file1.txt
echo "Path in $path2" # Path is ~/Docs/file1.txt
echo "Path in ${path}2" # Path is ~/Docs2
Запись (перезапись) значения:
<имя>=<значение>
Чтение:
$<имя> или ${<имя>}
path=~/
path2=$path/file.txt # path2=~/Docs/file1.txt
echo "Path in $path2" # Path is ~/Docs/file1.txt
echo "Path in ${path}2" # Path is ~/Docs2
Экспорт в дочерние процессы:
export <имя>=<значение>
export foo=93
Передача аргументов скрипту:
./script.sh arg1 arg2 arg3 ...
Обработка внутри скрипта:
$0 имя скрипта
$1, $2, $3, ... параметры скрипта
$# количество аргументов
$@ параметры скрипта
$* параметры скрипта (одной строкой)
var="Первый аргумент равен $1"
var="Десятый аргумент равен ${10}"
echo "Всего аргументов - $#"
echo $@
Пример:
#!/bin/bash
echo "Hello, who am I talking to?"
read varname
echo "It is nice to meet you $varname"
Пример:
$ ./introduction.sh
Hello, who am I talking to?
Misha
It is nice to meet you Misha
$
Результат:
Синтаксис:
Условия (строки):
if [[ условие ]]
then
# действия, если истина
fi
-z <строка> # строка пуста
-n <строка> # строка не пуста
<стр1> == <стр2> # строки равны
<стр1> != <стр2> # строки не равны
Пример:
if [[ -z $1 ]]
then
echo "Первый аргумент пуст!"
fi
if [[ $var1 == $var2 ]]
then
echo "Переменные равны!"
fi
Операции вида "-xx" - только для чисел!
Операции-знаки - только для строк!
Для чисел / строк:
-eq == # равно
-ne != # не равно
-lt < # меньше
-le # меньше или равно
-gt > # больше
-ge # больше или равно
Для файлов:
-e <путь> # путь существует
-f <путь> # это файл
-d <путь> # это директория
-s <путь> # размер не пустой
-x <путь> # файл исполняемый
Логические:
! # логическое отрицание
&& # логическое «И»
|| # логическое «ИЛИ»
if [[ условие ]]
then
# если истина
else
# если ложь
fi
if [[ условие1 ]]; then
# если условие1 истина
elif [[ условие2 ]]; then
# если условие1 ложь,
# но условие2 истина
else
# если оба ложь
fi
case переменная in
знач1)
# если переменная==знач1
;;
знач2)
# если переменная==знач2
;;
*)
# если переменная не равна
# ни знач1, ни знач2
esac
Синтаксис:
for переменная in список; do
# каждый раз переменная
# принимает следующее
# значение из списка
done
break прервать выполнение
continue перейти на следующее
значение
Пример:
for var in $(ls); do
echo "item: $var"
done
Синтаксис:
while [[ условие ]]; do
# пока условие истинно
done
Пример:
while read -r url; do
echo "$url"
done < list_of_urls.txt
Синтаксис:
let "переменная = выражение"
Пример:
Операции:
+, -, /, * | стандартные |
% | остаток от деления |
** | возведение в степень |
let "c = 1 + 1"
let "c = a + b"
Синтаксис:
переменная=$(программа)
Альтернативный синтаксис:
переменная=`программа`
Пример:
content=$(car file.txt)
files=$(ls ~/)
Код возврата:
0 | корректное завершение |
не 0 | завершение с ошибкой |
Узнать код:
$?
Выйти с кодом:
exit <код>
Пример:
touch file.txt
echo $?
Проверка кода возврата:
if $(программа); then
# если код 0
else
# если код не 0
fi
Синтаксис:
имя_функции() {
# действия с $1, $2, ... , $#
}
Использование:
...
имя_функции арг1 арг2 ...
...
Альтернативный синтаксис:
function имя_функции {
# действия с $1, $2, ... , $#
}
Нельза смешивать определения!
function имя_функции() {
# действия с $1, $2, ... , $#
}
return завершает исполнение функции
function имя_функции {
...
return 1
}
Глобальные и локальные переменные:
имя_функции() {
var_global=1
local var_local=2
}
Использование:
var_global=0
имя_функции
echo $var_global # 0
echo $var_local # 2
$ plagues=(blood frogs lice flies)
$ echo ${plagues[0]}
blood
$ echo ${plagues[*]}
blood frogs lice flies
$ plagues[3]=disease
$ echo ${plagues[*]}
blood frogs lice disease
echo ${#plagues[*]}
4
Подробный листинг файлов: ls -l:
1 2 3 4 5 6 7 8 -rw-r--r-- 1 misha group 23 Dec 2 19:13 p.tar -rw-rw-r-- 1 misha stud 34 Nov 1 19:13 exams
3 и 4 колонки - имена владельца пользователя и владельца группы.
Владелец нового файла - его создатель.
chown пользователь:группа путь
изменить обладателя
$ chown zoidberg file.txt
$ chown :futurama file.txt
Пример:
chgrp группа путь
изменить владельца-группу файлов
В Unix 3 класса доступа к файлу:
В каждом классе задается 3 права:
Права доступа листинга в первой колонке
(первый символ - тип файла)
-rw-r--r-- 1 misha group 36 Dec 2 19:13 r.txt drwxr-xr-- 1 misha group 64 Aug 1 11:03 temp -rwxr-xr-- 2 misha stud 48 Dec 2 15:13 a.out -rw-r--r-- 1 misha group 76 Feb 1 09:13 con.c
'-' означает отсутствие права
Права могут быть изменены только владельцем или супер-пользователем
chmod file1 file2...
u g o a
+ - =
r w x
Для смены прав есть команда chmod:
Пример:
$ chmod g-wx ownfile
В одной команде можно задавать права сразу для нескольких классов:
$ chmod a+w file1 file2
$ chmod go=r file
$ chmod g+x-w file
$ chmod u+w,og+r-w file
Краткая запись для задания всех 9 прав:
$ chmod 754 file.txt
Т.е. команду выше можно выразить так:
$ chmod u=rwx,g=rx,o=r file.txt
Владелец | Группа | Остальные |
---|---|---|
rwx | r-x | r-- |
111 | 101 | 100 |
7 | 5 | 4 |
Для разные типов файла разные значения прав доступа
Для обычных файлов все просто:
Для запуска shell-скрипта необходимы права на выполнение И чтение.
r | чтение содержимого (cat) |
w | редактирование файла |
x | запуск скрипта |
r | узнать содержимое директории |
w | создавать и удалять файлы в директории |
x | 1) войти в директорию 2) посмотреть метаданные файлов в директории |
Удаление файла не требует права на файл
Суперпользователь:
root (группа root)
Выполнить от имени root:
sudo команда
sudo mkdir dir
sudo chmod -r dir
Порядок выполнения проверки прав:
проверяется только право его класса
$ ls
file1.txt
file2.txt
file3.txt
file4.txt
pic1.jpg
pic2.jpg
$ ls *.jpg
pic1.jpg
pic2.jpg
* 0 и более любых символов
Пример:
$ ls
file1.txt
file2.txt
file3.txt
file4.txt
pic1.jpg
pic2.jpg
$ ls file?.txt
file1.txt
file2.txt
file3.txt
file4.txt
? 1 любой символ
Пример:
$ ls
file1.txt
file2.txt
file3.txt
file4.txt
pic1.jpg
pic2.jpg
$ ls *[0-3].*
file1.txt
file2.txt
pic1.jpg
pic2.jpg
[...] 1 из перечисленных символов
Пример:
$ ls
file1.txt
file2.txt
file3.txt
file4.txt
pic1.jpg
pic2.jpg
$ ls *[^0-3].*
file4.txt
* 1 из перечисленных символов
Пример:
mkdir ./{dir1,dir2,dir3}
создать директории dir1, dir2 и dir3.
touch ~/{file1,file2}.txt
создать файлы file.txt1 и file2.txt в
домашней директории
Стандарт POSIX
Поддерживаются в утилитах Unix
Perl Compatible Regular Expressions
Из Perl синтаксис заимстован в Java, .NET, Python, Ruby, JavaScript, и т.д.
Формальный язык поиска и манипуляций с подстроками в тексте, основанный на использовании метасимволов (wildcard).
По сути это "шаблон", состоящий из символов и метасимволов, задающий правило поиска.
Символы в шаблонах делятся на два типа:
Литералы:
[ ] \ ^ $ . | ? * + ( ) { }
Например: \[ или \$
Обозначает один любой символ
Например:
st..d # регулярное выражение
Под его описание подходит:
standard
stand
astddd
Позволяет указать, что на данном месте в строке может стоить один из указанных символов
^ (крышка)
Символ | Позиция | Пример | Результат |
---|---|---|---|
^ | Начало строки | ^a | aaa aaa |
$ | Конец строки | a$ | aaa aaa |
\b | Граница слова | a\b | aaa aaa |
\ba | aaa aaa | ||
\B | Не граница слова | \Ba\B | aaa aaa |
Символ | Повторений | Пример | Результат |
---|---|---|---|
{n} | n раз | colou{3}r | colouuur |
{m,n} | от m до n | colou{2,4}r | colouur, colouuur, colouuuur |
{m,} | не менее m | colou{2,}r | colouur, colouuur... |
{,n} | не более n | colou{,3}r | color, colour, colouur, colouuur |
* или {0,} | 0 или более | colou*r | color, colour... |
+ или {1,} | 1 или более | colou+r | colour, colouur... (но не color) |
? или {0,1} | 0 или 1 | colou?r | color, colour |
Проверка MAC-адреса:
^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$
Круглые скобки используются для определения области действия и приоритета операций
Например, выражение (тр[ау]м-?)* найдет последовательность вида трам-трам-трумтрам-трум-трамтрум
Шаблон
(та|ту)-\1
Найдет
"та-та" или "ту-ту", но не "та-ту"
(?:шаблон)
Под результат такой группировки не выделяется отдельная область памяти и, соответственно, ей не назначается номер
Это положительно влияет на скорость выполнения выражения
Самостоятельно (есть в домашке)
Что еще есть в PCRE?
grep "подстрока" файл
найти строки с подстрокой в файле
grep -c "подстрока" файл
посчитать количество вхождений строки
grep -r "подстрока" директория
найти строку во всех файлах в каталоге
grep "hello" file.txt
найти "hello" в файле file.txt
grep -c "123" file.txt
посчитать количество раз, которое "123"
встречается в файле "file.txt"
grep -r "world" ~/
найти "world" во всех файлах в
домашней директории
grep -l "строка" файл
список файлов с этой строкой
grep -L "строка" файл
список файлов, где этой строки нет
grep -n "строка" файл
выводить число строк в файле
grep -m число "строка" файл
не искать дальше после заданного
числа вхождений
grep -A число "строка" файл
выводить число строк после вхождения
grep -B число "строка" файл
выводить число строк до вхождения
grep -C число "строка" файл
выводить число строк до и после
вхождения
grep -E "шаблон" файл
найти указанный шаблон в файле
grep -E "^go" файл
найти строки, начинающиеся с "go"
grep -E "go$" файл
найти строки, оканчивающиеся на "go"
grep -E "c[au]t" файл
найти все строки, содержащие cat и cut
grep -E " [a-z]ight " файл
слова из 5 букв, кончающиеся на "ight"
grep -E " [a-zA-Z]ight " файл
аналогично, но слова могут начинаться
с заглавной буквы
grep -E " [a-z]*ight " файл
слова из 4+ букв, кончающиеся на "ight"
grep -E " [a-z]+ight " файл
слова из 5+ букв, кончающиеся на "ight"
grep -E " [a-z]?ight " файл
слова из 4-5 букв, кончающиеся на "ight"
find директория -name "имя_файла"
найти указанный файл в директории
find ~/ -name "file.txt"
найти file.txt в домашней директории
find ~/ -name "*.txt"
найти все текстовые файлы в
домашней директории
find дир -iname "имя_файла"
не учитывать регистр
find дир -path "путь"
найти указанный путь
find дир -size размер
найти файлы указанного размера
find дир -maxdepth число
искать не более чем на заданное
число уровней вниз
find дир -mindepth число
искать начиная с заданного числа
уровней вниз
Пример:
for i in $(ls *.mp3); do
some_command $1
done
Не сработает, если в названии будет пробел.
for i in *.mp3; do
some_command "$1"
done
Как правильно:
Пример:
cp $file $target
Не сработает, если имя содержит пробел или/и начинается с дефиса.
cp -- "$file" "$target"
Как правильно:
Двойной дефис сообщает, что опций больше не будет.
Пример:
somecmd 2>&1 >>logfile
Перенаправления выполняются слева направо до выполнения команды.
somecmd >>logfile 2>&1
Как правильно:
https://mywiki.wooledge.org/BashPitfalls
(очень рекомендуется к прочтению!)
ShellCheck статический анализатор
кода для Bash.
В браузере: https://shellcheck.net
Можно установить локально:
$ sudo apt-get install shellcheck
$ brew install shellcheck
Есть плагины для Vim, Emacs, VS Code...
В IntelliJ IDEA тоже есть плагин для Bash.
Есть поддержка ShellCheck и множество дополнительных инспекций.