← Весь справочник

cat и tac

Вывести файл, склеить несколько файлов, пронумеровать строки, показать невидимые символы

cat (от concatenate — «сцепить») читает файлы по очереди и выводит их содержимое подряд. Им смотрят короткие файлы, склеивают несколько файлов в один, создают файл из here-doc и проверяют, нет ли в тексте табуляций, \r и пробелов в конце строк. tac делает то же самое, но выводит строки в обратном порядке — от последней к первой.

Синтаксис

cat [опции] [файл…]
tac [опции] [файл…]

Без файлов или с - вместо имени обе команды читают стандартный ввод. cat a - b выведет a, затем стандартный ввод, затем b.

Опции cat

Нумерация и пустые строки

ОпцияЧто делает
-nнумеровать все строки, включая пустые
-bнумеровать только непустые строки (перекрывает -n)
-sсхлопнуть несколько пустых строк подряд в одну

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

Невидимые символы

ОпцияЧто делает
-Eпоказать конец строки как $: так видны пробелы в конце
-Tпоказать табуляцию как ^I
-vпоказать управляющие символы в нотации ^X (\r → ^M, \x01 → ^A), а байты больше 127 — как M-…; перевод строки и табуляцию не трогает
-Aвсё сразу: то же, что -vET
-eто же, что -vE
-tто же, что -vT
-uигнорируется, оставлена для совместимости

Опции tac

ОпцияЧто делает
-s строкаразделитель «строк» — эта строка вместо перевода строки
-rсчитать разделитель из -s регулярным выражением
-bставить разделитель перед записью, а не после

Here-doc: создать файл из текста

# переменные и $(…) внутри раскрываются
cat <<EOF > app.conf
host=$HOSTNAME
port=8080
EOF

# слово-ограничитель в кавычках: текст пишется как есть, без подстановок
cat <<'EOF' > script.sh
echo "$HOME"
EOF

# <<- убирает ведущие табуляции (не пробелы!) — удобно внутри if и функций
cat <<-EOF
	отступ табуляцией исчезнет
	EOF

# дописать в конец файла, а не перезаписать
cat <<EOF >> app.conf
debug=false
EOF

Примеры

printf 'one\n\n\n\ttwo  \nthree\r\n' > sample.txt

# просто вывести файл
cat sample.txt

# склеить файлы в один (порядок — как в аргументах)
printf 'a\n' > part1; printf 'b\n' > part2
cat part1 part2 > all.txt

# номера строк: все / только непустые
cat -n sample.txt
cat -b sample.txt

# убрать лишние пустые строки
cat -s sample.txt

# увидеть табуляции (^I), \r из Windows (^M) и пробелы перед $
cat -A sample.txt

# вставить стандартный ввод между двумя файлами
echo '---' | cat part1 - part2

# последние строки лога — первыми
printf '10:00 start\n10:05 work\n10:10 stop\n' | tac

# tac с другим разделителем
printf 'a,b,c,' | tac -s ,

Подводные камни

  • cat a b > a молча теряет a. Оболочка обнуляет a до запуска cat, в результате в файле окажется только b, и ошибки не будет. Пиши в новый файл и потом переименуй.
  • cat f >> f не зацикливается, а падает с ошибкой input file is output file и кодом 1.
  • Последняя строка без перевода строки склеится со следующим файлом. Если a кончается на b без \n, то cat a c выведет bc одной строкой. Проверить можно через tail -c1 файл | xxd.
  • tac на такой строке тоже «склеивает»: для ввода 1\n2 без финального \n выйдет 21\n.
  • -v в локали C (как в песочнице) показывает кириллицу как мусор вида M-PM-^P, потому что каждый байт UTF-8 больше 127. Для поиска только \r и табуляций это не мешает.
  • <<- убирает только табуляции. Если редактор заменил их пробелами, отступ останется, а закрывающий EOF с пробелами не распознается вовсе — here-doc «съест» остаток скрипта.
  • Лишний cat в конвейере («useless use of cat»): cat file | grep x работает, но запускает лишний процесс. grep x file или grep x < file делают то же. Это не ошибка, просто привычка, которую стоит знать; к тому же команда с файлом в аргументах может напечатать его имя и узнать размер.
  • Не выводи cat-ом бинарные файлы в терминал: управляющие байты могут сбить настройки терминала. Смотри их через xxd и od или cat -v.
  • Большой файл целиком в терминал — неудобно. Для просмотра начала или конца бери head и tail, для листания — less.

См. также

head и tail · nl · tee · перенаправления · xxd и od · rev