Все главы учебника
Содержание учебника
Глава 03 / Linux

Оболочка, пути и кавычки: что получает команда

10 мин чтенияКонтент v0.10.0

В проекте есть файл lesson notes.txt. Вы вводите его имя в команду и получаете две ошибки: инструмент ищет lesson и notes.txt отдельно. Файл цел, а проблема возникла ещё до его открытия. Оболочка превратила строку в аргументы, которые не совпали с вашим намерением.

В прошлом уроке вы отличили shell от ядра. Сейчас посмотрим, как оболочка выбирает команду, подставляет значения и передаёт аргументы. Для упражнений используем Bash. Если текущая оболочка другая, выполните bash; команда exit позже вернёт в предыдущую. Возможности Bash не надо автоматически переносить на /bin/sh или PowerShell.

Где начинается путь

Абсолютный путь начинается с / и идёт от корня файловой системы. Относительный отсчитывается от текущего рабочего каталога процесса. . обозначает этот каталог, .. — его родителя. Домашний каталог текущего пользователя shell может подставлять вместо ~.

pwd
cd "$HOME"
pwd
ls .

Кавычки вокруг $HOME сохраняют значение как один аргумент. cd меняет каталог текущей оболочки, но не двигает файлы. Пути ./report.txt и report.txt здесь называют один объект. После перехода в другой каталог тот же относительный путь может назвать уже другой файл.

Начнём отдельную лабораторию:

lab_dir=$(mktemp -d)
cd "$lab_dir"
mkdir 'project notes'
printf 'draft\n' > 'project notes/lesson notes.txt'
pwd

mktemp -d создаёт новую временную папку и печатает её путь. Конструкция $(...) подставляет вывод команды. Переменная lab_dir хранит полученный путь. Он будет отличаться на разных машинах; не переписывайте пример буквальным /tmp-именем. Перенаправление > создаёт или перезаписывает файл, поэтому здесь оно используется только для нового учебного объекта.

Строка и аргументы

Shell разбивает команду на слова, обрабатывает кавычки и подстановки, затем запускает программу с аргументами. Кавычки обычно не передаются программе как часть имени: они управляют разбором строки. Одинарные кавычки сохраняют буквальный текст. Двойные допускают подстановку переменных, сохраняя результат одним аргументом.

name='lesson notes.txt'
printf '<%s>\n' "$name"
printf '<%s>\n' '$name'
cat "project notes/$name"

Первый вывод — <lesson notes.txt>, второй — <$name>, а cat покажет draft. Команда printf выводит текст по заданному формату; %s обозначает строку. Кавычки различаются не красотой оформления, а правилами подстановки.

Некавыченная $name может разбиться по пробелам и подвергнуться раскрытию шаблонов. Это опасно для имён с пробелами, звёздочками и переводами строк. Для аргумента, который должен представлять одно значение, начинайте с "$name". Не пытайтесь лечить уже неправильно разобранное имя добавлением sudo.

Шаблон раскрывает shell

Звёздочка * в некавыченном слове подбирает подходящие имена текущего каталога. Это glob, не регулярное выражение и не команда поиска внутри файлов. Например:

printf 'a\n' > alpha.txt
printf 'b\n' > beta.txt
printf '%s\n' *.txt
printf '%s\n' '*.txt'

Первый вызов обычно выводит alpha.txt и beta.txt, второй — буквальное *.txt. В Bash без дополнительных настроек шаблон без совпадений может остаться буквальным. Не стройте скрипт на предположении, что пустой поиск всегда даёт пустой список. Регулярные выражения для текста появятся позже.

Имена с начальным - некоторые программы принимают за опции. Путь ./-report.txt явно содержит имя файла, а многие GNU-инструменты поддерживают -- как конец опций. Это разные способы избежать неоднозначности. Поддержку конкретной команды проверяйте в справке, а не считайте любое -- универсальным.

Найти справку и команду

type cd
type printf
type cat
man pwd

type объясняет, встроена ли команда в shell, является ли псевдонимом или внешним файлом. Несколько команд одного имени могут существовать одновременно. В man обычно нажимают q для выхода, / для поиска. В минимальном образе справочник может отсутствовать; используйте официальный manual и вернитесь к установке пакетов в соответствующей главе.

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

Самостоятельная лаборатория

Создайте подкаталог с пробелом и два файла: один с пробелом, другой со звёздочкой в имени. Покажите содержимое каждого по точному пути. Затем из родительского каталога найдите тот же объект абсолютным и относительным путём. Запишите аргументы, которые вы намеревались передать, до запуска команды.

Критерий готовности: ваша команда читает ровно выбранный файл, кавычки сохраняют одно имя, а pwd объясняет смысл относительного пути. Для проверки используйте printf '<%s>\n' ... вместо случайного копирования. Файл со звёздочкой должен читаться как буквальное имя, а не как весь набор совпадений.

Разбор

cat "$lab_dir/project notes/lesson notes.txt" работает независимо от текущего каталога, если переменная сохранилась. cat 'project notes/lesson notes.txt' работает из лабораторной папки. Новая оболочка не обязана знать вашу переменную — окружение изучим отдельно. Пока сохраните путь в заметке и оставьте лабораторию для исследования файлов.

Первичные источники: GNU Bash: quoting, Bash shell expansions, GNU Coreutils: pwd.