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