Learning Platform
Глоссарий Troubleshooting
Урок 05.02 · 18 мин
Начальный
pwdcdlsNavigationeza

pwd, cd, ls — основа навигации

Эти три команды вы будете писать сотни раз в день. pwd — где я? cd — переместиться. ls — что здесь? Простые на вид, но за ними много нюансов и полезных опций, которые отличают Junior от Middle.

В этом уроке разберём каждую с опциями, ловушками и современными альтернативами.


pwd — где я нахожусь

pwd (Print Working Directory) — самая простая команда. Выводит абсолютный путь текущей директории.

$ pwd
/home/user/linux-sandbox/lesson-03

Это builtin bash — он не запускает отдельную программу, а выводит значение переменной $PWD:

$ echo $PWD
/home/user/linux-sandbox/lesson-03

$ type pwd
pwd is a shell builtin

Есть ещё $OLDPWD — где вы были до этого:

$ cd /tmp
$ echo $OLDPWD
/home/user/linux-sandbox/lesson-03

$ cd -      # переключиться обратно (toggle)
/home/user/linux-sandbox/lesson-03

cd - — супер полезный shortcut: переключает между двумя последними директориями.

TIP

pwd -P (physical) показывает путь без symlinks (resolved). По умолчанию pwd показывает логический путь с symlinks как есть. Если /home/user — symlink на /mnt/users/user, pwd покажет /home/user, pwd -P покажет /mnt/users/user. Иногда это важно для скриптов.


cd — change directory

$ cd /etc                  # абсолютный путь
$ cd ../home               # относительный (на уровень вверх + в home)
$ cd ~                     # домой
$ cd                       # тоже домой (без аргумента)
$ cd -                     # в предыдущую директорию
$ cd ~user                 # в /home/user (другого пользователя)
$ cd ~/projects/airflow    # подкаталог home

Полезные хитрости:

# Если в имени директории пробелы — кавычки
$ cd "/path with spaces/foo"

# Можно использовать $PWD/relative
$ cd "$PWD/subdir"

# cd $variable — работает, если в переменной — путь
$ DIR=/var/log
$ cd $DIR

В bash есть CDPATH — аналог PATH для cd:

$ export CDPATH=".:$HOME:$HOME/projects:/etc"
$ cd ssh
/etc/ssh                   # нашёл /etc/ssh, потому что /etc в CDPATH

Это редко используется, потому что путает: непонятно, куда ты попадёшь.


pushd / popd — stack of directories

Для тех, кто часто прыгает между несколькими директориями, есть pushd и popd. Это стек.

$ pwd
/home/user

$ pushd /tmp
/tmp ~                     # показывает текущий стек

$ pushd /var/log
/var/log /tmp ~

$ dirs
/var/log /tmp ~

$ popd
/tmp ~                     # вернулся в /tmp

$ popd
~                          # вернулся в home

Это удобно для скриптов, когда нужно «перейти, сделать дело, вернуться». Подробнее в модуле 17.


ls — самая используемая команда

ls (LiSt). Базовый вызов:

$ ls
file1.txt   file2.csv   subdir/

Самые полезные опции:

ls — главные опции
-lLong format. Показывает права, владельца, размер, дату, имя. Самый частый формат для DE
-aAll. Показывает скрытые файлы (начинающиеся с .). Без -a не видны .bashrc, .git, .ssh
-hHuman-readable размеры (1.5K, 200M, 4.2G) вместо байтов. Работает с -l
-tSort by modification time. Самые свежие сверху. С -tr — самые свежие внизу
-rReverse порядок сортировки. По умолчанию по имени a->z, с -r будет z->a
-SSort by size, большие сверху. С -Sr — наоборот
-RRecursive — рекурсивно по всем подпапкам. Может быть медленно на большой иерархии
-dDirectory only — для самой папки, не её содержимого. Например `ls -ld dir` покажет инфо о dir
-iInode номер. Полезно для hard links — два файла с одним inode — это один файл
-1Один файл на строку (без многоколончатого вывода). Для парсинга в скриптах
--colorЦветной вывод. По умолчанию auto: цвета в терминале, без цветов в pipe
--group-directories-firstСначала папки, потом файлы. По умолчанию смешано

Самая частая комбинация — ls -la:

$ ls -la ~
total 88
drwxr-xr-x 15 user user 4096 May 13 14:00 .
drwxr-xr-x  3 root root 4096 May  1 12:00 ..
-rw-------  1 user user 5847 May 13 14:00 .bash_history
-rw-r--r--  1 user user  220 May  1 12:00 .bash_logout
-rw-r--r--  1 user user 3771 May  1 12:00 .bashrc
drwx------  2 user user 4096 May 13 14:00 .cache
drwx------  3 user user 4096 May  1 12:00 .config
drwx------  3 user user 4096 May 13 14:00 .ssh
-rw-r--r--  1 user user  807 May  1 12:00 .profile
drwxr-xr-x  5 user user 4096 May 13 14:00 projects

Колонки слева направо:

  1. Тип + права (drwxr-xr-x): первый символ — тип файла (d = directory, - = file, l = symlink). Остальные 9 — права (модуль 6).
  2. Количество hard links (15): для папок — число подпапок + 2 (. и ..).
  3. Владелец (user).
  4. Группа (user).
  5. Размер в байтах (4096). Для папок 4096 — размер inode-таблицы, не «размер содержимого».
  6. Дата изменения (May 13 14:00).
  7. Имя.

ls -lh: размеры по-человечески

$ ls -lh /var/log
-rw-r----- 1 syslog adm 12K Apr 14 15:00 auth.log
-rw-r----- 1 syslog adm 156K Apr 14 14:00 auth.log.1
-rw-r----- 1 syslog adm 2.3M Apr 13 06:25 auth.log.2.gz
-rw-r----- 1 syslog adm 1.5G May 13 14:00 syslog

С -h размеры в килобайтах/мегабайтах/гигабайтах. Без него — сырые байты.


ls —time-style=long-iso

По умолчанию ls показывает дату в локальной форме (May 13 14:00). Это не идеально для машинного парсинга. Альтернативы:

# ISO формат: 2026-05-13 14:00
$ ls -l --time-style=long-iso

# Полный ISO с секундами
$ ls -l --time-style=full-iso
-rw-r--r-- 1 user user 220 2026-05-13 14:00:35.123456789 +0000 .bash_logout

long-iso — это золотая середина для DE: машиночитаемо, читаемо людьми, сортируется правильно как строка (потому что год->месяц->день).

Многие DE добавляют в .bashrc:

alias ll='ls -lh --time-style=long-iso --color=auto'

Скрытые файлы

Файлы, начинающиеся с точки (.bashrc, .git, .env), считаются скрытыми. Скрыты они от стандартного ls. С -a показываются:

$ ls
projects   notes.txt

$ ls -a
.            .bash_history  .git           projects
..           .bashrc        .ssh           notes.txt

. и .. — это special-имена: «текущая папка» и «родительская». Они есть в каждой директории (так устроена FS). ls -A (большая A) — все скрытые, но без . и ..:

$ ls -A
.bash_history  .bashrc  .git  .ssh  projects  notes.txt

В Linux нет понятия «скрытый атрибут» как в Windows. Скрытость определяется именно префиксом . в имени.


ls с цветами

Современные ls раскрашивают вывод:

  • Синий — директории
  • Зелёный — исполняемые файлы
  • Cyan — symlinks
  • Красный — архивы
  • Magenta — изображения
  • Белый — обычные файлы

Это всё определяется в $LS_COLORS (длинная переменная):

$ echo $LS_COLORS | tr ':' '\n' | head -10
rs=0
di=01;34
ln=01;36
mh=00
pi=40;33
so=01;35
do=01;35
bd=40;33;01
cd=40;33;01
or=40;31;01

Подробнее: dircolors -p покажет описание всех правил.


eza — modern замена ls

eza — это переписанный на Rust ls, с улучшениями:

  • Лучшие цвета и эмодзи для типов файлов;
  • Встроенная git-info колонка;
  • Tree-mode (eza --tree);
  • Поддержка extended attributes из коробки;
  • Лучшие defaults.
# Установка
$ sudo apt install -y eza
# или
$ brew install eza

# Замена ls для интерактива
$ alias ls=eza
$ alias ll='eza -lah --git'

# С git-status:
$ eza -lah --git
Permissions Size User  Date Modified    Git Name
drwxr-xr-x     - user  13 May 14:00     -  .git
.rw-r--r--   220 user  13 May 14:00     M- .bashrc
.rw-r--r--  3.7K user  13 May 14:00     -- README.md
drwxr-xr-x     - user  13 May 14:00     N- new-folder

Колонка Git показывает: M- (modified), N- (new/untracked), -- (no changes). Это супер-полезно: видишь сразу, что изменено, прямо в листинге.

TIP

Совет: alias-ить ls на eza НЕ стоит. Если потом запустите скрипт, который зависит от стандартного вывода ls (например, ls -la | awk), сюрпризы. Лучше alias-ить ll/ll/tree, а оригинальный ls оставить нетронутым.


ls на macOS — BSD ls

На macOS ls — это BSD-вариант (от FreeBSD/Apple), не GNU. Опции немного отличаются:

# BSD ls (macOS, по умолчанию)
$ ls -G                    # цветной вывод (вместо --color)
$ ls -lT                   # вывести время в полной форме

# GNU ls (через brew)
$ brew install coreutils
# coreutils ставит как gls, gcp, gmv и т.д.
$ gls --color

Самое заметное:

  • BSD ls: -G для цветов, GNU ls: --color=auto.
  • BSD ls: нет --time-style=long-iso.
  • BSD ls: нет --group-directories-first.

Для скриптов, которые должны работать и на Linux, и на macOS, либо избегать GNU-специфичных опций, либо ставить coreutils и использовать gls.


ls в скриптах — НЕ парсите вывод

Важное правило: никогда не парсите вывод ls в скриптах. Имена файлов могут содержать пробелы, переводы строк, специальные символы — ls форматирует их для человека, а не для машины.

Вместо ls в скриптах используйте:

# Цикл по файлам — встроенный glob
for f in *.csv; do
    process "$f"
done

# find для рекурсии или фильтров
find . -name "*.csv" -type f -print0 | xargs -0 process

# При необходимости — массив
files=(*.csv)
echo "Found ${#files[@]} CSV files"

find -print0 и xargs -0 решают проблему пробелов в именах. Подробнее в модуле 4.4 (find).


Попробуй сам

Создайте sandbox и поиграйте:

$ mkdir -p ~/linux-sandbox/lesson-nav
$ cd ~/linux-sandbox/lesson-nav
$ touch file1.txt file2.txt "file with spaces.txt" .hidden
$ mkdir subdir1 subdir2 .hidden-dir

# Сравните разные ls:
$ ls
$ ls -a
$ ls -la
$ ls -la --time-style=long-iso

# Сортировка по времени:
$ touch oldest.txt
$ sleep 1
$ touch middle.txt
$ sleep 1
$ touch newest.txt
$ ls -lt    # newest первым
$ ls -ltr   # newest последним

# Inode:
$ ls -i
123456 file1.txt    123457 file2.txt    ...

# pwd toggle:
$ cd /tmp
$ cd -          # обратно в lesson-nav
$ cd -          # снова в /tmp

Поставьте eza:

$ sudo apt install -y eza
$ eza -lah --git ~
$ eza --tree --level=2 ~/linux-sandbox

Проверка знанийKnowledge check
Junior пишет в скрипте: `for f in $(ls *.csv); do process $f; done`. Тестирует — работает. Через неделю файл получает имя 'sales report 2026.csv' (с пробелами) и скрипт падает: `process: cannot find sales`. Что не так?
ОтветAnswer
Несколько проблем сразу. (1) ls *.csv форматирует вывод как для человека, разделяя имена пробелами или переводами строк. Когда имя файла САМО содержит пробелы (как 'sales report 2026.csv'), ls не экранирует их — они смешиваются с разделителями. (2) $(ls ...) без кавычек подвергается word splitting в bash: пробел = новое слово. Скрипт думает, что есть три файла: 'sales', 'report', '2026.csv'. process получает только 'sales' и падает. Правильное решение: НЕ парсить ls в скриптах. Использовать встроенный glob: for f in *.csv; do process "$f"; done. Кавычки вокруг $f обязательны — они защищают от word splitting. Glob возвращает массив правильно с пробелами и спецсимволами. Если нужна рекурсия — find . -name '*.csv' -print0 | xargs -0 process (null-separator решает проблему пробелов).

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 5. Что делает `cd -`?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5