Unix 2019

Контакты

  • Курс длится 1 модуль
  • 6 ДЗ и КР в конце
  • Балл за КР блокирующий (порог 0.4)
  • Оценка по 10-балльной шкале:

      ДЗ * 0.7 + КР * 0.3

 

Организационная информация

  • Жесткий - начало следующей практики
  • Мягкий - воскресенье 18:00
  • Если вы прислали дз...
    • до мягкого - я гарантированно проверю решение и дам возможность исправить замечания до жесткого
    • после мягкого, но до жесткого - я с небольшой вероятностью проверю ваше решение и дам возможность исправить замечания до жесткого
    • после жесткого - :(

Дедлайны

Лекция 1

Ликбез по Unix, bash-скрипты, регулярные выражения

Краткий обзор

Состоит из:

  • Kernel - ядро, основная программа Unix. Контролирует железо, CPU, память, диски, сеть и т.п.
  • Shell - текстовый интерфейс между пользователем и системой.

Обзор

  • Bourne shell compatible

sh, ash, bash, dash, ksh, zsh...

  • C shell compatible

csh, tcsh

  • Exotic

es (functional), psh (Perl), pysh (Python)

Unix Shells

  • Разработан для проекта GNU в замен sh.
  • Основной shell для GNU/Linux и macOS.

 

Особенности:

  • Редактирование командной строки
  • История команд
  • Переменные $RANDOM и $PPID
  • Автодополнение
  • ...

Bourne Again Shell (bash)

Hello, World!

$ 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 число файл

    вывести последние строки файла

head / tail

wc файл

    подсчет слов, строк, символов и байт

 

wc -l файл

    подсчет строк

 

wc -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

Конвеер (pipe)

передать stdin Прогр1 в качестве stdin для Прогр2, далее stdout Прогр2 в качестве stdin для Прогр2 и т.д.

Чуть-чуть про процессы

Пример: запуск интерпретатора Python

Остановка процесса

$ python
>>> 1 + 1
2
>>> 2 + 2
4
>>> # Как завершить работу?

Способ 1 (верный): Ctrl-D

$ python
>>> 1 + 1
2
>>> <EOF> # ^D

^D    отправляет на вход EOF (end-of-line),

         т.е. сообщает, что ввод окончен

Способ 2: Ctrl-C

$ python
>>> 1 + 1
2
>>> # ^C
KeyboardInterrupt

^C    прерывает текущий процесс

Способ 3: Ctrl-Z

$ python
>>> 1 + 1
2
>>> # ^Z
[1]+  Stopped  python

^Z    остановить процесс

foreground

$ fg
python
1 + 1
2
>>> 

fg    продолжить выполнение остановленной задачи в интерактивном режиме

background

$ bg
[1]+ python &

bg    продолжить выполнение остановленной задачи в фоновом режиме

fg и bg    принимают номер задания. При вызове без параметров применяются к последнему заданию.

jobs

$ jobs
[1]- Stopped cmd1
[2]+ Running cmd2 &

jobs    показать запущенные задания  

Фоновый режим

$ cmd &
[3] 24128

Можно сразу запустить команду в фоновом режиме (вместо использования ^Z и bg)

stop    остановить фоновое задание

wait    дождаться завершения задания

            вернуть его код возврата

Обратно к фильтрам

sort    сортирует файлы по строкам

 

Некоторые опции:

Фильтры: sort

-r выводить в обратном порядке
-n сортировать как числа
-u только уникальные строки
-f игнорировать регистр

uniq    фильтрует повторяющиеся строки

 

Некоторые опции:

Фильтры: uniq

-c перед каждой строкой выводить число дубликатов
-d только повторяющиеся строки
-u только строки без дубликатов
-i игнорировать регистр

fold   

    разбивает длинные строки на несколько

 

Некоторые опции:

Фильтры: fold

-w <n> максимальная длина строка

tr  <src> <dst>

    мапает символы из входной строки

 

Некоторые опции:

Фильтры: tr

-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

Bash скрипты

Простой скрипт hello_world.sh:

Shebang

#!/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

Условия (строки):

if [[ условие ]]
then
  # действия, если истина
fi
-z <строка>      # строка пуста
-n <строка>      # строка не пуста
<стр1> == <стр2> # строки равны
<стр1> != <стр2> # строки не равны

Пример:

Ветвление: if

if [[ -z $1 ]]
then
  echo "Первый аргумент пуст!"
fi

if [[ $var1 == $var2 ]]
then
  echo "Переменные равны!"
fi

Операции вида "-xx" - только для чисел!

Операции-знаки - только для строк!

Для чисел / строк:

-eq  ==  # равно
-ne  !=  # не равно
-lt  <   # меньше
-le      # меньше или равно
-gt  >   # больше
-ge      # больше или равно

Ветвление: if

Для файлов:

-e <путь> # путь существует
-f <путь> # это файл
-d <путь> # это директория
-s <путь> # размер не пустой
-x <путь> # файл исполняемый

Логические:

!  # логическое отрицание
&& # логическое «И»
|| # логическое «ИЛИ»

Условия

Ветвление: if-else

if [[ условие ]]
then
  # если истина
else
  # если ложь
fi

Ветвление: if-elif-else

if [[ условие1 ]]; then
  # если условие1 истина
elif [[ условие2 ]]; then
  # если условие1 ложь,
  # но условие2 истина
else
  # если оба ложь
fi

Ветвление: case

case переменная in
знач1)
  # если переменная==знач1
  ;;
знач2)
  # если переменная==знач2
  ;;
*)
  # если переменная не равна
  # ни знач1, ни знач2
esac

Синтаксис:

Циклы: for

for переменная in список; do
  # каждый раз переменная
  # принимает следующее
  # значение из списка
done

break        прервать выполнение


continue  перейти на следующее
                   значение

Пример:

Циклы: for

for var in $(ls); do
  echo "item: $var"
done

Синтаксис:

Циклы: while

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    завершает исполнение функции

  • может возвращать "код завершения" (записывается в переменную $?)
  • Если код не указан, возвращает код последней команды

Функции: 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

Права доступа

  • Unix - многопользовательская система
  • У каждого объекта есть идентификатор и права доступа:
    • UID    идентификатор пользователя
    • GID    идентификатор группы
    • inode    идентификатор файла

Общие понятия

  • Файлы в Unix имеют двух владельцев
    • Пользователя (user owner)
    • Группу (group owner)
  • Владелец-пользователь можен не являться членом группы
  • Группы нужны для совместного пользования файлом

Владельцы файлов

Подробный листинг файлов: 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 класса доступа к файлу:

  • User access (u)    для владельца
  • Group access (g)    для членов группы
  • Other access (o)    для всех остальных

В каждом классе задается 3 права:

  • Read    на чтение
  • Wrire    на запись
  • eXecute    на выполнение

Права доступа к файлу

Права доступа листинга в первой колонке

(первый символ - тип файла)

Пример

-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

Суперпользователь

Порядок выполнения проверки прав:

  • Для суперпользователя проверка прав не производится
  • Если операция запрашивается
    • владельцем-пользователем
    • членом группы
    • другим пользователем

      проверяется только право его класса

Проверка прав доступа

Регулярные выражения

Wildcards: *

$ ls
file1.txt
file2.txt
file3.txt
file4.txt
pic1.jpg
pic2.jpg
$ ls *.jpg
pic1.jpg
pic2.jpg

*    0  и более любых символов

 

Пример:

Wildcards: ?

$ 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  любой символ

 

Пример:

Wildcards: [...]

$ 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 из перечисленных символов

 

Пример:

Wildcards: [^...]

$ 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

  • Basic Regular Expressions (BRE)
  • Extended Regular Expressions (ERE)

Поддерживаются в утилитах Unix

 

Perl Compatible Regular Expressions

Из Perl синтаксис заимстован в Java, .NET, Python, Ruby, JavaScript, и т.д.

Стандарты

Формальный язык поиска и манипуляций с подстроками в тексте, основанный на использовании метасимволов (wildcard).

 

По сути это "шаблон", состоящий из символов и метасимволов, задающий правило поиска.

Регулярные выражения

Символы в шаблонах делятся на два типа:

  • Литералы - обычные символы
  • Метасимволы - символы, которые используются для замены других символов или их последовательностей

Шаблоны

Литералы:

  • все символы за исключением специальных:

[ ] \ ^ $ . | ? * + ( ) { }

  • специальные символы, предваренные символом \

      Например: \[ или \$

Литералы

Обозначает один любой символ

 

Например:

Метасимвол .

st..d # регулярное выражение

Под его описание подходит:

  • standard
  • stand
  • astddd

Позволяет указать, что на данном месте в строке может стоить один из указанных символов

  • [A-Z] - любая заглавная латинская буква
  • [a-d] - строчная буква от a до d
  • [A-Za-z0-9] - латинская буква или цифра
  • [А-Яа-яЁё] - любая русская буква

Символьные классы

  • Спецсимвол отрицания в символьных классах:

^ (крышка)

  • [^abc] - все символы, кроме букв латинского алфавита a, b, c.

Символьные классы

  • Вертикальная черта разделяет допустимые варианты
  • Например, "gray|grey" соответствует "gray" или "grey"
  • "gr(a|e)y" тоже описывает строки "gray" и "grey"

Альтернативы

Позиция внутри строки

Символ Позиция Пример Результат
^ Начало строки ^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

Найдет

"та-та" или "ту-ту", но не "та-ту"

Пример

(?:шаблон)

    Под результат такой группировки не выделяется отдельная область памяти и, соответственно, ей не назначается номер

    Это положительно влияет на скорость выполнения выражения

Группировка без обратной связи

Самостоятельно (есть в домашке)

Lookaheads и lookbehinds

Что еще есть в PCRE?

  • Ленивые квантификаторы
  • Сверхжадные квантификаторы
  • Именованные группы связывания
  • Рекурсивные шаблоны
  • Сокращенные записи символьных классов: \w, \W, \s, \S...

Выражения в стиле Perl

grep "подстрока" файл

    найти строки с подстрокой в файле

 

grep -c "подстрока" файл

    посчитать количество вхождений строки

 

grep -r "подстрока" директория

    найти строку во всех файлах в каталоге

grep

grep "hello" file.txt

    найти "hello" в файле file.txt

 

grep -c "123" file.txt

    посчитать количество раз, которое "123"

    встречается в файле "file.txt"

 

grep -r "world" ~/

    найти "world" во всех файлах в

    домашней директории

grep

grep -l "строка" файл

    список файлов с этой строкой

 

grep -L "строка" файл

    список файлов, где этой строки нет

grep

grep -n "строка" файл

    выводить число строк в файле

 

grep -m число "строка" файл

    не искать дальше после заданного

    числа вхождений

grep

grep -A число "строка" файл

    выводить число строк после вхождения

 

grep -B число "строка" файл

    выводить число строк до вхождения

 

grep -C число "строка" файл

    выводить число строк до и после

    вхождения

grep

grep -E "шаблон" файл

    найти указанный шаблон в файле

 

grep -E "^go" файл

    найти строки, начинающиеся с "go"

 

grep -E "go$" файл

    найти строки, оканчивающиеся на "go"

grep

grep -E "c[au]t" файл

    найти все строки, содержащие cat и cut

 

grep -E " [a-z]ight " файл

    слова из 5 букв, кончающиеся на "ight"

 

grep -E " [a-zA-Z]ight " файл

    аналогично, но слова могут начинаться

    с заглавной буквы

grep

grep -E " [a-z]*ight " файл

    слова из 4+ букв, кончающиеся на "ight"

 

grep -E " [a-z]+ight " файл

    слова из 5+ букв, кончающиеся на "ight"

 

grep -E " [a-z]?ight " файл

    слова из 4-5 букв, кончающиеся на "ight"

grep

Find

find директория -name "имя_файла"

    найти указанный файл в директории

 

find ~/ -name "file.txt"
    найти file.txt в домашней директории

 

find ~/ -name "*.txt"
    найти все текстовые файлы в

    домашней директории

find

find дир -iname "имя_файла"

    не учитывать регистр

 

find дир -path "путь"
    найти указанный путь

 

find дир -size размер
    найти файлы указанного размера

find

find дир -maxdepth число

    искать не более чем на заданное

    число уровней вниз

 

find дир -mindepth число

    искать начиная с заданного числа

    уровней вниз

find

Частые ошибки программирования

Пример:

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

      (очень рекомендуется к прочтению!)

  • Перевод немного устаревшей версии:

      http://www.binsh.ru/tag/bash-pitfalls

Bash Pitfalls

ShellCheck

ShellCheck    статический анализатор

                         кода для Bash.

 

В браузере: https://shellcheck.net

 

Можно установить локально:

  • Debian/Ubuntu

 

  • masOS

 

$ sudo apt-get install shellcheck
$ brew install shellcheck

Интеграция в редактор

Есть плагины для Vim, Emacs, VS Code...

 

В IntelliJ IDEA тоже есть плагин для Bash.

Есть поддержка ShellCheck и множество дополнительных инспекций.

Q & A

Made with Slides.com