Служебные символы

Служебные символы используемые в shell скриптах

# -- Начало комментария.
Все что следует за этим символом, является комментарием, исключением является только комбинация #! стоящая в первой строке. Любые команды, следующие за этим символом в одной строке, будут считаться комментариями и выполнены не будут.

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

  1. echo "Здесь символ # не является началом комментария."
  2. echo 'Здесь символ # тоже не является началом комментария.'
  3. echo Здесь экранированный символ \# тоже не является началом комментария.
  4. echo А здесь # означает комментарий.
  5.  
  6. echo ${PATH#*:}       # Подстановка параметров -- символ # не является началом комментария.
  7. echo $(( 2#101011 ))  # База системы счисления -- символ # не является началом комментария.

Экранируется символ #, символом \.

Кроме вышеописанных ситуаций, символ # не интерпретируется как начало комментария в операциях поиска по шаблону.

; -- Разделитель команд ( точка с запятой )
Позволяет записывать более одной команды в строке.
  1. echo hello; echo there

В некоторых ситуациях, данный служебный символ необходимо экранировать, как и знак начала комментария.
;; -- Разделитель в операторе case ( двойная точка с запятой )
  1. case "$variable" in
  2. abc)  echo "$variable = abc" ;;
  3. xyz)  echo "$variable = xyz" ;;
  4. esac

. -- Точка, аналог встроенной в оболочку bash, команды source.
При использовании внутри сценария, позволяет подгружать внешний файл, например с данными или функциями.<
Например, есть файл test.sh содержащий следующий сценарий:

  1. #!/bin/bash
  2.  
  3. . var.file  # загружаем переменные из внешнего файла 
  4. echo $var  # выводим значение переменной

файл var.file содержит всего одну строку, где переменной $var присваивается значение Hello world !

  1. var="Hello world !"

Запускаем сценарий test.sh

freebsd /# ./test.sh
Hello world !

Так-же "точка" может быть частью имени файла. Если имя файла начинается с точки, как правило, такой файл будет скрытым для просмотра командой ls ( зависит от оболочки ).

Если речь идет о каталогах, одна точка означает текущий каталог, две точки каталог уровнем выше, то есть родительский.

Команду точка, удобно использовать при копировании или перемещении объектов файловой системы. Например так:

freebsd /# cp /path/to/dir/* . # Копировать все файлы из директории /path/to/dir/ в текущую директорию

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

" -- Двойные кавычки
В строке, заключенной в двойные кавычки, не интерпретируются ( экранируются ) большинство служебных символов.
' -- Одинарные кавычки
Более строгий вариант экранирования. В строке, заключенной в одинарные кавычки, не будут интерпретированы любые служебные символы.
, -- Запятая
Команда запятая, используется для вычисления нескольких арифметических выражений. Несмотря на то, что вычислены будут все выражения, результат будет выведен только из последней операции. Например, такой скрипт:

  1. #!/bin/bash
  2.  
  3. let "result = ((a= 5 + 3, b= 7 - 1, c= 15 - 4))"
  4.  
  5. echo $a
  6. echo $b
  7. echo $c
  8. echo $result

выведет следующие результаты:

freebsd /# ./test.sh
8  # результат первой операции, присвоенный переменной $a
6  # результат второй операции, присвоенный переменной $b
11 # результат третьей операции, присвоенный переменной $c
11 # результат опять-же третьей операции, поскольку она последняя в последовательности выражений, присвоенный переменной $result
\ -- Escape ( обратный слэш )
Используется для экранирования отдельных служебных символов в строке. По эффекту действия данный символ аналогичен одинарным кавычкам:

  1. echo '$'  # напечатает символ $
  2. echo \$ # так-же напечатает символ $

/ -- Слэш
Используется в качестве разделителя в путях директорий и файлов, в операционных системах Unix.

При использовании в арифметических операциях, означает - деление.

` -- Подстановка команд ( обратные кавычки )
Могут используются для присвоения переменной, результатов выражения системной команды. Скрипт:

  1. #!/bin/bash
  2.  
  3. result= `hostname` # результат команды hostname присваиваем переменной 
  4. echo $result

выведет

freebsd /# ./test.sh
freebsd.host     # результат выполнения команды hostname
: -- Пустая операция ( двоеточие )
Является аналогом операции "NOP" ( нет операции ). Данную команду можно считать эквивалентом встроенной команды true. Как и true, команда двоеточие, всегда возвращает 0 ( ноль ), то есть значение истина ( true ).

Практически все команды в операционных системах unix, возвращают "0" в случае успешного завершения работы.

Возможны следующие варианты использования.
Бесконечный цикл:

  1. while :
  2. do
  3. echo "test"
  4. done
  5.  
  6. # то-же самое но с использованием <em>true</em>
  7. # while true
  8. # do
  9. # echo "test"
  10. # done

Символ заполнитель в условном операторе if/then.

  1. a=1
  2. b=2
  3. if [ $a = $b ]
  4. then :      # Не производить никаких действий
  5. else
  6. echo "test"  # поскольку условие возвращает false ( $a не равно $b ), будет выполнена эта строка
  7. fi

Символ заполнитель в операциях, предполагающих наличие двух операндов.

  1. : ${username=`whoami`} # без символа двоеточия будет выдано сообщение об ошибке

Символ заполнитель в конструкциях вложенный документ.

В операциях с подстановкой параметров.

  1. : ${HOSTNAME?} ${USER?} ${MAIL?}
  2. # если одна или несколько переменных не определены, будет выведено сообщение об ошибке

В операциях замены подстроки с подстановкой переменных.

В сочетании с операторами перенаправления вывода

При использовании с оператором >, обнуляет содержимое файла, если файла не существует, он создается:

  1. : > data.file  # этой командой файл <em>data.file</em> будет очищен до нуля.

Того-же можно добиться с помощью команды cat /dev/null > data.file, только в этом случае создается новый процесс.

В сочетании с оператором >> перенаправление с добавлением в конец файла и изменением времени последнего доступа.

  1. : >> data.file 

При задании имени не существующего файла, он будет создан, аналогично вышеописанному варианту или действию команды touch.

Два предыдущих варианта неприменимы к символическим ссылкам, конвейерам и другим специальным файлам.

Кроме перечисленного, символ двоеточие можно использовать для создания комментариев, но это не рекомендуется, поскольку при использовании символа #, интерпретатор не проверяет данную строку на предмет ошибок, при использовании двоеточия это не так:

  1. : такой комментарий, приведет к сообщению об ошибке, ( if [ $x -eq 3] ).

Так-же символ двоеточие используется в качестве разделителя полей в файле /etc/passwd и переменной окружения $PATH.

freebsd /# echo $PATH
/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/root/bin
! -- Логическое отрицание в условных операторах
Символ восклицательный знак используется для инвертирования кода возврата операции к которой он применяется. Так-же применяется для логического отрицания в операциях сравнения:

  1. if [ $a = $b ] # истина, если $a равно $b
  2. if [ $a != $b ] # данное условие истинно если $a НЕ РАВНО $b

Восклицательный знак является зарезервированным словом оболочки bash.

В некоторых случаях может быть использован для косвенного обращения к переменным.

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

* -- Символ группового шаблона ( звездочка )
Используется в качестве шаблона для постановки в имени файла. В случае использования одиночного символа шаблона, означает совпадение с любым именем файла.

freebsd /# echo *
file1.sh file2.sh file3.sh arch1.tar arch2.tar

В следующем варианте выведет файлы с любым именем, но только с расширением tar

freebsd /# echo *.tar
arch1.tar arch2.tar

В регулярном выражении, означает 0 или больше, любых символов.

В арифметических операциях знак * - означает умножение, а в варианте ** - возведение в степень.

? -- Проверка условия
В некоторых случаях используется для проверки выполнения условия.

При использовании в конструкциях с двойными скобками, ведет себя как тернарный оператор языка C ( и многих других языков ).

  1. (( t = a<6?10:20 ))   # Тернарный оператор
  2. echo "If a < 6, then t = 10, else t = 20." # то-же самое, традиционный вариант

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

  1. : ${HOSTNAME?} ${USER?} ${MAIL?}
  2. # если одна или несколько переменных не определены, будет выведено сообщение об ошибке

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

$ -- Подстановка переменной
  1. a=5
  2. b=10
  3.  
  4. echo $a     # выведет 5
  5. echo $b     # выведет 10

Установка символа $ перед именем переменной, означает что будет получено значение данной переменной.

В регулярных выражениях, означает конец строки.

${} -- Подстановка переменной
Выполняет то-же действие, что и предыдущий вариант, но в некоторых случаях при возникновении неоднозначности интерпретации, будет работать только этот вариант. Кроме того может быть использован для конкатенации строковых переменных в одну строку.

  1. id=${USER}-on-${HOSTNAME}
  2. echo "$id"

выведет

freebsd /# ./test.sh
root-on-freebsd.grt
$*, $@ -- Аргументы командной строки
Переменная $* содержит все параметры командной строки в виде строки.

Переменная $@ тоже содержит все параметры командной строки, но строку из себя представляет каждый параметр, то есть они не интерпретируются.

$? -- Код завершения операции
Данная переменная получает код, возвращаемый последней выполненной командой, функцией или сценарием.
$$ -- PID процесса
Переменная содержит process id текущего сценария.
() -- Группа команд
Команды размещенные в скобках, выполняются в дочернем процессе ( subshell ). При этом переменные, определяемые в дочернем процессе, не видны в родительском.
  1. var=12345
  2. ( var=54321;  )  # переменная определяется в дочернем процессе
  3. echo "var = $var"

выведет

freebsd /# ./test.sh
a = 12345

Другой вариант использования конструкции с одинарными скобками, инициализация массивов.

  1. array=(element1 element2 element3)

{xxx,yyy,zzz,...} -- Фигурные скобки
Интерпретируется как список возможных вариантов. Например, следующая команда сценария, производит поиск строки test в файлах data.1, data.2, data.3.

  1. grep test data.{1,2,3*}

и выводит найденные варианты

freebsd /# ./test.sh
data.1:test
data.3:test

Использовать в фигурных скобках пробелы можно, либо заключив их в одинарные или двойные кавычки, либо экранировав их с помощью символа \.

  1. echo {test1,test2}\ :{\ A," B",' C'}

выведет

freebsd /# ./test.sh
test1 : A test1 : B test1 : C test2 : A test2 : B test2 : C
{} -- Блок кода ( вложенный блок )
По сути такая конструкция создает анонимную функцию. В отличии от традиционно создаваемых функций, переменные вложенного блока, доступны всему сценарию.

  1. a="test"
  2. { a=1111; }
  3. echo "a = $a"

будет выведено:

freebsd /# ./test.sh
a = 1111

Конструкция заключенная в фигурные скобки, может создавать перенаправление ввода/вывода.

Перенаправление ввода/вывода из вложенного блока:

  1. #!/bin/bash
  2.  
  3. file=/etc/fstab
  4. {
  5. read line1
  6. read line2
  7. } < $file # считываем строки из файла fstab
  8.  
  9. echo "$line1"
  10. echo "$line2"
  11. exit 0

в результате выполнения этого сценария, будут выведены две первые строки файла /etc/fstab

freebsd /# ./test.sh
# Device                Mountpoint      FStype  Options         Dump    Pass#
/dev/da0s1b             none            swap    sw              0       0

Сохранить результат работы вложенного блока в файл

  1. #!/bin/bash
  2. # rpm-check.sh
  3.  
  4. # Этот сценарий получает описание rpm-пакета, список файлов, и проверяет возможность установки.
  5. # Результат работы сохраняется в отдельном файле.
  6.  
  7. SUCCESS=0
  8. E_NOARGS=65
  9.  
  10. if [ -z "$1" ]
  11. then
  12.   echo "Порядок использования: `basename $0` rpm-file"
  13.   exit $E_NOARGS
  14. fi
  15.  
  16. {
  17.   echo
  18.   echo "Описание архива:"
  19.   rpm -qpi $1       # Получаем описание rpm пакета
  20.   echo
  21.   echo "Список файлов:"
  22.   rpm -qpl $1       # Получаем список файлов пакета
  23.   echo
  24.   rpm -i --test $1  # Проверяем, возможно-ли установить данный пакет
  25.   if [ "$?" -eq $SUCCESS ]
  26.   then
  27.     echo "$1 установка возможна"
  28.   else
  29.     echo "$1 -- установка не возможна"
  30.   fi
  31.   echo
  32. } > "$1.test"       # Перенаправление результатов во внешний файл.
  33.  
  34. exit 0

В отличии от конструкций с обычными одинарными скобками, выполняющимися в дочернем процессе, вложенные блоки в фигурных скобках, выполняются в рамках того-же процесса, что и сам сценарий.

{} \; -- Путь к файлу и его имя
Чаще всего применяется с командой find

Обратите внимание что символ точка с запятой, завершающий опцию --ezec, команды find, должен быть экранирован, что-бы избежать его интерпретации.

[ ] -- test
В конструкции с квадратными скобками, проверяется истинность включенного в него выражения.

  1. var=1
  2. if [ $var = 1 ]
  3. then
  4. echo "var= $var"
  5. else :
  6. fi

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

  1. array=(a b c)  # создаем массив
  2. echo ${array[1]} # выводим второй элемент массива

Нумерация элементов массива начинается с 0 ( ноль ), поэтому в элементе с индексом 1, находится символ b .

При использовании в регулярных выражения, в квадратных скобках, пишутся так называемые классы символов или диапазоны.

[xyz] - соответствует любому из этих трех символов
[0-9] - соответствует любому числовому символу от 0 до 9
[a-zA-Z] - соответствует любой, прописной или строчной букве, английского алфавита

[[]] -- Двойные квадратные скобки
Это расширенный вариант конструкция с одинарными квадратными скобками, в двойных квадратных скобках также проверяется истинность, заключенного в данную конструкцию, выражения, но этот вариант более предпочтителен, поскольку позволяет избежать некоторых логических ошибок. Например в конструкции с двойными квадратными скобками, допустимо использовать операторы &&, ||, < и >, в то время как в одинарных скобках они приведут к ошибке.

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

(( )) -- Двойные круглые скобки
Между двойными круглыми скобками, вычисляется целочисленное арифметическое выражение. Кроме того двойные скобки позволяют работать с переменными в стиле языка C:
  1. #!/bin/bash
  2. echo
  3. (( a = 23 ))  # присваиваем значение переменной
  4. echo "a ( ) = $a"
  5. (( a++ ))  # пост-инкремент значения переменной $a, в стиле языка C
  6. echo "a ( a++) = $a"
  7. (( a-- ))  # пост-декремент значения переменной $a, в стиле языка C
  8. echo "a ( a--) = $a"
  9. (( ++a )) # пред-инкремент значения переменной $a, в стиле языка C
  10. echo "a ( ++a) = $a"
  11. (( --a ))  # пред-декремент значения переменной $a, в стиле языка C
  12. echo "a ( --a) = $a"

так-же можно использовать тернарные операторы, упомянутые ранее:

  1. (( t = a<6?10:20 )) 

>, &>, >&, >>, < -- Перенаправление ввода/вывода
В любой unix системе, по умолчанию открыто три файла stdin ( стандартный поток ввода - клавиатура ), stdout ( стандартный потов вывода - экран ) и stderr ( стандартный поток вывода ошибок ), дескрипторы 0,1 и 2, соответственно.

Операторы перенаправления позволяют передать вывод из файла, сценария, команды или блока команд на ввод другого файла, сценария, команды. Например:

freebsd /# ./test.sh > outfile  # перенаправление вывода сценария stdout в файл outfile
freebsd /# command &> outfile # перенаправление выводов stdout и stderr команды в файл outfile
freebsd /# command >&2 # перенаправление вывода stdout команды в поток stderr
freebsd /# ./test.sh >> outfile # перенаправление вывода сценария stdout в файл, в режиме добавления в конец файла

Операция подстановки процесса, передает вывод одного процесса на ввод другого.

  1. (command)>
  2. <(command)

между символами <, > и круглой скобкой не должно быть пробела.

Кроме того символы < и > используются в операциях сравнения символов и целых чисел.

<< -- Перенаправление на встроенный документ
Встроенный документ, специальный вид перенаправления, позволяющий передать интерактивной команде или программе, список команд. Например, сценарий с выводом многострочного текста с помощью программы cat, может выглядеть так:
  1. #!/bin/bash
  2.  
  3. cat <<End-of-message
  4. -------------------------------------
  5. line one
  6. line two
  7. line three
  8. -------------------------------------
  9. End-of-message
  10. exit 0

на выходе получим следующее:

freebsd /# ./test.sh
-------------------------------------
line one
line two
line three
-------------------------------------

Символ-ограничитель, в нашем примере End-of-message, не должен повторяться в теле самого встроенного документа.

<, > -- Посимвольное ASCII-сравнение
Сравниваются ASCII коды символов

  1. if [[ "$a" < "$b" ]]
  2. if [ "$a" \< "$b" ]
  3. if [[ "$a" > "$b" ]]
  4. if [ "$a" \> "$b" ]

Обратите внимание, при использовании операций сравнения в одинарных квадратных скобках, символы больше и меньше, необходимо экранировать обратным слэшем

\<, \> -- Граница слова
Данные символы используются для обозначения границ слова в регулярных выражениях, например в операциях поиска.

grep '\' textfile  # найти все вхождения отдельного слова the, такие слова как them или other, учтены не будут
| -- Конвейер
Конвейер ( канал, pipe ), это классический способ межпроцессного взаимодействия, stdout одного процесса, передается на stdin другого. Часто используется для связывания нескольких команд между собой. Одна команда, передает результат обработки данных через конвейер на ввод другой команды. Например, вывод команды ps ( process status - список процессов ), передается на ввод команде grep ( поиск по шаблону ), которая в свою очередь, сделав выборку, выводит результат в stdout.

freebsd /# ps aux | grep sshd
root    1274  0.0  0.2 25108  4460  ??  Is   Mon03PM   0:00.01 /usr/sbin/sshd
root    1349  0.0  0.2 37040  5164  ??  Ss   Mon03PM   0:06.84 sshd: root@pts/0 (sshd)
root   22977  0.0  0.1  8060  1396   1  RL+   9:18PM   0:00.00 grep sshd

или еще пример, команда cat выводит содержимое файла на вход команды wc, которая посчитает количество строк и выведет результат.

freebsd /# cat test.sh | wc -l
9

В конвейеры можно объединять как команды, так и сценарии. Например, перенаправим вывод команды ls на вход сценария, преобразующего символы в верхний регистр:

  1. #!/bin/bash
  2.  
  3. tr 'a-z' 'A-Z'
  4. exit 0

freebsd /# ls -l | ./test.sh # делаем перенаправление
TOTAL 6688
-RWXR--R--   1 ROOT  WHEEL       28 JUL 25 18:34 1.PHP
-RWXR--R--   1 ROOT  WHEEL       75 APR  4 09:57 1.PL
-RWXR--R--   1 ROOT  WHEEL       60 APR  4 16:47 1.SH

Все символы, вывода команды ls, будет преобразован в верхний регистр.

Stdout каждого процесса в конвейере, должен читаться в stdin другого процесса, иначе конвейер оборвется:

cat file | ls -l | sort # здесь вывод содержимого файла командой cat уйдет в никуда, в результате на выходе мы получим не то, что ожидаем

Конвейер выполняется в отдельном процессе, поэтому не может получить доступ к переменным сценария.

Если какая-то из команд конвейера завершается аварийно, весь конвейер аварийно завершает работу.

>| -- Принудительное перенаправление
Перенаправление происходит даже если bash, используется с ключом -C ( noclobber ).
|| -- Логическое ИЛИ
В операциях сравнения, ||, возвращает значение true, если хотя-бы одно условие возвращает true:
  1. #!/bin/bash
  2.  
  3. a=1
  4. b=2
  5. if [ $a -eq 10 ] || [ $b -eq 2 ]
  6. then
  7. echo "true"
  8. else
  9. echo "false"
  10. fi

этот небольшой сценарий выведет true, поскольку второе условие вернет true, то и вся проверка вернет true.

Вышеприведенное условие можно записать в следующей форме:

  1. if [[ $a -eq 10 || $b -eq 2 ]]

ну или аналог

  1. if [ $a -eq 10 -o $b -eq 2 ]

Оператор ||, не может использоваться в одинарных квадратных скобках.

& -- Выполнить процесс в фоновом режиме
Команда, за которой стоит символ & ( амперсанд ), будет выполняться в фоновом режиме.

При использовании в сценариях, в фоновом режиме можно выполнять не только команды, но и циклы, например так:

  1. #!/bin/bash
  2.  
  3. for i in 1 2 3 4 5 6 7 8 9 10
  4. do
  5. echo -n "$i "
  6. done &
  7. echo
  8.  
  9. for i in 11 12 13 14 15 16 17 18 19 20
  10. do
  11. echo -n "$i "
  12. done
  13. echo
  14.  
  15. exit 0

Обратите внимание, команда, запущенная из сценария в фоновом режиме, может съесть вывод фоновой команды. Например, следующий сценарий:

  1. #!/bin/bash
  2.  
  3. ls -l & # команда ls запускается в фоне
  4. echo "Done."

выведет такой результат:

freebsd /# ./test.sh
Done.

как видите, результат выполнения команды ls, отсутствует.
Что-бы исправить поведение сценария, достаточно использовать оператор wait, который приостанавливает выполнение сценария, до тех пока, пока не будут завершены все фоновые задания. Приводим сценарий к следующему виду:

  1. #!/bin/bash
  2.  
  3. ls -l &
  4. echo "Done."
  5. wait

теперь мы получим ожидаемый вывод:

freebsd /# ./test.sh
Done.
total 6688
-rwxr--r--   1 root  wheel       28 Jul 25 18:34 1.php
-rwxr--r--   1 root  wheel       75 Apr  4 09:57 1.pl
-rwxr--r--   1 root  wheel       60 Apr  4 16:47 1.sh
&& -- Логическое И
В условных операциях, &&, возвращает true только в том случае, если ОБА операнда имеют значение true.
Формат использования аналогичен оператору || ( логическое ИЛИ ).
  1. if [ $a -eq 1 ] && [ $b -eq 2 ]

или

  1. if [[ $a -eq 10 && $b -eq 2 ]]

или

  1. if [ $a -eq 10 -a $b -eq 2 ]

- -- Дефис
Часто дефис предшествует опциям команд.

ls -l

Для многих команд наличие дефиса перед ключами опция не обязательно, например у команды ps, тем не менее бывают ситуации когда его использование необходимо, что-бы опции интерпретировались именно как опции а не как их значения.

Перенаправление из/в stdin или stdout

Пример перемещения дерева каталогов и файлов с помощью архиватора tar:

  1. (cd ./ss && tar cf - . ) | (cd ./test && tar xpvf -)

что делает данный сценарий

  • cd ./ss - перейти в каталог, расположенный в текущем каталоге, содержимое которого будем переносить
  • && - все последующие команды будут выполнены только после выполнения перехода в исходный каталог
  • tar cf - . -ключ c говорит архиватору tar создать новый архив, ключ f ( file ) с последующим - задается файл архива -- stdout, в архив помещается текущий каталог ( . ) со всем содержимым.
  • | ( ... ) - конвейер в дочерний процесс
  • cd ./test - Перейти в каталог назначения
  • && - как и выше
  • tar xpvf - - распаковать tar архив ( ключ x ), сохранить принадлежность и права доступа к файлам ( ключ p ), выдавая подробные данные во время выполнения ( ключ v ), файл архива stdin ( ключ f с последующим - )

Еще один пример:

freebsd /# echo "hello" | cat -
hello

В таком контексте - ( дефис ), скорее не отдельный оператор bash, а опция, распознаваемая Unix утилитами ( tar, cat и т.д. ), выводящими результаты в stdout.

Если предполагается имя файла, -, перенаправляет вывод в stdout или принимает ввод с stdin.

При запуске программы file без параметров, будет выдано сообщение об ошибке:

freebsd /# file
Usage: file [-bcikLhnNrsvz0] [-e test] [-f namefile] [-F separator] [-m magicfiles] file...

если передать в качестве параметра - ( дефис ), file будет ожидать пользовательского ввода:

freebsd /# file -
aaaaa
/dev/stdin: ASCII text

freebsd /# file -
#!/bin/bash
/dev/stdin: POSIX shell script text executable

как видите, программа file проанализировала стандартный поток ввода stdin и определила тип его содержимого.

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

  1. #!/bin/bash
  2.  
  3. file="./text.txt"
  4. title="this is first line"
  5. echo $title | cat - $file >$file.new

на выходе получаем файл text.txt.new, содержащий все предыдущие данные, плюс первую строку "this is first line".

Теперь более полный пример использования архиватора tar с символом -. Небольшой скрипт для архивирования файлов, подвергшихся изменениям в течение последних суток:

  1. #!/bin/bash
  2.  
  3. BACKUPFILE=backup
  4. archive=${1:-$BACKUPFILE} # если имя для архива не задано в командной строке, будет назначено имя по умолчанию <em>backup.tar.gz</em>
  5.  
  6. tar cvf - `find . -mtime -1 -type f -print0 | xargs -0 tar rvf "$archive.tar"`
  7. gzip $archive.tar
  8. echo "done"
  9. exit 0

Оператор перенаправления - может конфликтовать с именами файлов, начинающихся с дефиса -filename, что-бы этого избежать, в сценариях необходимо проверять имена файлов и предварять их префиксом пути, например: ./-filename или $PWD/-filename.
Кроме того не забывайте о значениях переменных, простой пример:

  1. var="-n"
  2. echo $var

этот сценарий ничего не выведет, поскольку итоговая команда получится echo -n, то есть значение переменной, "-n", будет интерпретировано как опция команды echo, просто подавляющая вывод символов новой строки.

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

В арифметических выражениях, означает операцию вычитания.

Не забывайте, интерпретация символа - ( дефис ), зависит от контекста, в котором вы его используете.

= -- Символ равно
В зависимости от контекста применения, выступает в роли операции присваивания значений переменных:
  1. a=100
  2. b="test"
  3. echo $a # выведет 100
  4. echo $b # выведет test  

или как знак равенства в операциях сравнения.

+ -- Плюс
В зависимости от контекста использования, оператор сложения в арифметических операциях или квантификатор в регулярном выражении.
В регулярных выражениях означает, одно или несколько совпадений предыдущего символа.
% -- Модуль
В зависимости от контекста использования, остаток от деления в арифметических операциях или выступает в качестве шаблона.

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

~ -- Домашний каталог ( тильда )
Соответствует переменной окружения $HOME, содержащей путь к домашнему каталогу текущего пользователя.

freebsd /# echo ~
/root

freebsd /# ls -l ~  # листинг домашнего каталога текущего пользователя
total 47030
-rw-------  1 root        wheel            120 Aug 28 23:56 .bash_history
drwxr-xr-x  5 root        wheel            512 Jul 16 16:54 .cpan
-rw-r--r--  1 root        wheel            940 Jul  5 12:16 .cshrc
drwxr-xr-x  3 root        wheel            512 Jun 24 02:41 .gem
~+ -- Текущий рабочий каталог
Соответствует переменной окружения $PWD, содержащей имя текущего рабочего каталога.
~- -- Предыдущий рабочий каталог
Соответствует переменной окружения $OLDPWD, содержащей имя предыдущего рабочего каталога.
^ -- Начало строки
При использовании в регулярных выражениях, обозначает начало строки текста.

Управляющий символ

В качестве управляющего символа, управляет выводом текста или поведением терминала. Набирается на клавиатуре как сочетание Ctrl+клавиша.

Ctrl+C - Прервать выполнение процесса.
Ctrl+D - Выход из системной оболочки, аналог команды exit или EOF- конец файла, так-же выступает завершающим символом при вводе с stdin.
Ctrl+G - BEL, звуковой сигнал.
Ctrl+H - Backspace, удалить предыдущий символ.
Ctrl+J - Возврат каретки.
Ctrl+L - Аналог команды clear, очистка окна терминала.
Ctrl+M - Перевод строки.
Ctrl+U - Очистить строку ввода.
Ctrl+X - Приостановить выполнение процесса.

Символ пробела
Пробелом считается сам символ пробела, символ табуляции, перевод строки, возврат каретки или комбинация из перечисленных символов. Используется как разделитель команд и переменных.
Поскольку bash довольно привередлив в отношении пробелов, есть строгие ограничения на использование пробельных символов в операциях присвоения значений переменным. Например:
  1. var = 123 # не правильный вариант, переменная будет интерпретирована как команда м аргументами = и 123
  2. var=123 # правильный вариант
  3.  
  4. let c = $a - $b # не правильный вариант
  5. let c=$a-$b # правильный
  6. let "c = $a - $b" # тоже допустимо
  7.  
  8. if [ $a -le 5] # не правильный вариант
  9. if [ $a -le 5 ] # правильный
  10. if [ "$a" -le 5 ] # тоже правильный
  11. [[ $a -le 5 ]] # тоже правильный

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

Переменная $IFS содержит разделитель полей, используемый некоторыми программами, по-молчанию, пробел.

Комментарии

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

$# - количество аргументов переданных скрипту

#!/bin/bash
#
for i in $*
do
echo "$i"
done
echo "All: $#"
exit 0
./test.sh 9 8 7 6 5 4
9
8
7
6
5
4
All: 6

$! - PID последнего

$! - PID последнего запущенного в фоне процесса

#!/bin/bash
#
for i in $(seq 1 10)
do
echo "$i"
sleep 1
done&
echo "PID: $!"
exit 0
root@debian:/home/metr/sh# ./test.sh
PID: 5147
root@debian:/home/metr/sh# 1
2
3
4
5
6
7
8
9
10