Представь что у тебя есть переменная:
И в скрипте мы делаем так:
Это ошибочный вариант, бэд мать его практика.
Команда
ㅤ
НО! Результат этой команды разбивается на части, если в нём есть пробелы.
Например:
Выдаст:
А если так:
Логично, получаем ошибку:
Bash думает что это два отдельных слова, а не один путь.
➡️ Бест-практика
1. Кавычки защищают результат команды от разбиения.
2. И
Как работают кавычки
- Когда Bash видит
- Кавычки внутри
- Кавычки снаружи не объединяются с внутренними.
Наглядно, можно представить так:
Внутренние кавычки
Внешние кавычки
Теперь даже если переменная будет содержать пробелы команда не разобьётся на части.
tags: #bash #badpractices #bestpractices
—
🔔 @bashdays➡️ @gitgate
f="My Documents/file.txt"
И в скрипте мы делаем так:
cd $(dirname "$f")
Это ошибочный вариант, бэд мать его практика.
Команда
cd $(dirname "$f")
должна вернуть путь к папке, где лежит файл.ㅤ
НО! Результат этой команды разбивается на части, если в нём есть пробелы.
Например:
dirname "My Documents/file.txt"
Выдаст:
My Documents
А если так:
cd My Documents
Логично, получаем ошибку:
cd: No such file or directory: My
Bash думает что это два отдельных слова, а не один путь.
cd -P -- "$(dirname -- "$f")"
1. Кавычки защищают результат команды от разбиения.
2. И
cd
получит целый путь, даже если в нём есть пробелы.Как работают кавычки
- Когда Bash видит
$(...)
, он воспринимает это как отдельную область, некий «уровень».- Кавычки внутри
$(...)
работают только внутри.- Кавычки снаружи не объединяются с внутренними.
Наглядно, можно представить так:
cd "$( dirname "$f" )"
Внутренние кавычки
"$f"
защищают переменную f
Внешние кавычки
""
защищают результат dirname "$f"
Теперь даже если переменная будет содержать пробелы команда не разобьётся на части.
tags: #bash #badpractices #bestpractices
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Вот те на!
Большинство думает, что
ㅤ
В Bash
Скобка
Команда выше напечатает
Теперь о главном
Если хочешь использовать
Плохая практика:
Внутри
Хорошая практика:
Если
И Всё работает как надо, без лишних скобок!
Выводы
Никогда не пиши
Пиши просто
tags: #bash #badpractices #bestpractices
—
🔔 @bashdays➡️ @gitgate
if [ false ]; then echo "HELP"; fi
Большинство думает, что
[
— это часть команды if
как скобки в других языках программирования. Но нихуя!ㅤ
В Bash
if
просто запускает команду. Команда [ ... ]
— это обычный бинарник, аналогично команде test
, а не специальный синтаксис. Скобка
]
нужна только для красоты и завершения команды [
.Команда выше напечатает
HELP
, потому что строка "false"
— непустая, а значит, условие считается истинным.Теперь о главном
Если хочешь использовать
grep
в if
, не надо писать скобки!Плохая практика:
if [ grep -q "foo" myfile ]; then
echo "Найдено!"
fi
[... ]
— ожидает условие, а не командуgrep
— это команда, а не логическое выражениеВнутри
[
запускать команды нельзя — это приведёт к ошибкеХорошая практика:
if grep -q "foo" myfile; then
echo "Найдено!"
fi
if
просто запускает grep
Если
grep
нашёл совпадение, он вернёт 0
(успех), и выполнится then
И Всё работает как надо, без лишних скобок!
[
— это как калькулятор, а grep
— это поиск. В калькуляторе искать бесполезно!Выводы
Никогда не пиши
if [ grep ... ]
— это ошибка!Пиши просто
if grep ...
, чтобы проверить результат команды.if
работает с командами. [
— это тоже команда, но не синтаксис.tags: #bash #badpractices #bestpractices
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Позволил себе пару дней ничего не делать, кроме конечно проверки LF домашек. Лежал, исследовал дырки в axiom verge, гулял. Мне понравилось!
ㅤ
Буду почаще практиковать. Но есть и жирный минус, сегодня пришлось себя прям заставлять что-то сделать по работе. К хорошему привыкаешь быстро.
Ладно, лирика. Давай дальше бест-практики тыкать.
Команда
Тут самое важно это — пробелы, про кавычки повторять не буду, ты это уже и так знаешь. Все уши тебе прожужал.
Неправильно:
1. Нельзя слеплять всё вместе. Это хуёва даже в плане кодстайла.
2. Нет пробела вокруг знака «=».
3. Аналогично, всё слеплено.
Правильный синтаксис:
или
Почему?
Потому что
Главное правило — всегда ставь пробелы между каждым элементом в условии.
tags: #bash #badpractices #bestpractices
—
🔔 @bashdays➡️ @gitgate
ㅤ
Буду почаще практиковать. Но есть и жирный минус, сегодня пришлось себя прям заставлять что-то сделать по работе. К хорошему привыкаешь быстро.
Ладно, лирика. Давай дальше бест-практики тыкать.
Команда
if [ bar = "$foo" ];
проверяет, равны ли два значения.Тут самое важно это — пробелы, про кавычки повторять не буду, ты это уже и так знаешь. Все уши тебе прожужал.
Неправильно:
[bar="$foo"]
[ bar="$foo" ]
[[bar="$foo"]]
1. Нельзя слеплять всё вместе. Это хуёва даже в плане кодстайла.
2. Нет пробела вокруг знака «=».
3. Аналогично, всё слеплено.
Правильный синтаксис:
if [ bar = "$foo" ]; then
или
if [[ bar = "$foo" ]]; then
Почему?
Потому что
[, =, ]
это отдельные символы, первая скобка вообще команда test
. А если ты все слепляешь, Bash посчитает тебя долбаёбом и отправит в пешее эротическое.Главное правило — всегда ставь пробелы между каждым элементом в условии.
tags: #bash #badpractices #bestpractices
—
Please open Telegram to view this post
VIEW IN TELEGRAM
И снова здравствуйте!
ㅤ
Давно хотел реализовать функцию на Bash, чтобы красиво выводить какие-то значимые уведомления в терминал по типу как это сделано в npm.
Обычное
Хуяк-хуяк и получился очередной ебальник-убивальник.
Всё просто! Передаем тип алерта и сообщение которое нужно выводить в рамке.
А чё, красиво получилось! Забирай себе, глядишь когда-нибудь пригодится.
➡️ Box-drawing characters
tags: #bash
—
🔔 @bashdays➡️ @gitgate
ㅤ
Давно хотел реализовать функцию на Bash, чтобы красиво выводить какие-то значимые уведомления в терминал по типу как это сделано в npm.
Обычное
echo
уже не возбуждает, ничего не поделаешь. Да и всякие Gum тоже ставить не хочется.Хуяк-хуяк и получился очередной ебальник-убивальник.
#!/bin/bash
bashdays_box() {
local headertext="$1"
local message="$2"
local white=$'\e[38;5;007m'
local reset=$'\e[0m'
local color
case "$headertext" in
INFO) color=$'\e[38;5;39m' ;;
OK) color=$'\e[38;5;34m' ;;
DONE) color=$'\e[38;5;34m' ;;
WARN) color=$'\e[38;5;214m' ;;
ERROR) color=$'\e[38;5;196m' ;;
DEBUG) color=$'\e[38;5;244m' ;;
TASK) color=$'\e[38;5;141m' ;;
NOTE) color=$'\e[38;5;45m' ;;
*) color=$'\e[38;5;244m' ;;
esac
local headerpadding=$(( ${#message} - ${#headertext} ))
local header=${message:0:headerpadding}
echo -e "\n${color}╭ ${headertext} ${header//?/─}────╮" \
"\n│ ${message//?/ } │" \
"\n│ ${white}${message}${color} │" \
"\n│ ${message//?/ } │" \
"\n╰──${message//?/─}────╯${reset}"
}
bashdays_box "INFO" "Hello from https://t.me/bashdays"
bashdays_box "ERROR" "Swap is enabled — this may affect performance"
bashdays_box "WARN" "Certificate expires in 5 days"
bashdays_box "DEBUG" "Using config file: /etc/myapp/config.yml"
bashdays_box "DONE" "All services started"
Всё просто! Передаем тип алерта и сообщение которое нужно выводить в рамке.
А чё, красиво получилось! Забирай себе, глядишь когда-нибудь пригодится.
tags: #bash
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Все знают команду
🔤 🔤 🔥 🔤 🔤 🔤 🔤
Очень удобная команда, имеет очень много форматов и позволяет складывать/вычитать даты, например:
Но в bash есть еще средства для работы со временем:
ㅤ
Переменная
Переменная
Обратите внимание, число секунд не зависит от часового пояса.
Обратите внимание, разделитель дробной части может быть различным, в зависимости от языковых настроек.
Переменные
И еще есть специальный формат оператора
Например:
Если не указать переменную или указать -1 - будет использовано текущая дата/время. Если указать -2 - будет использовано время начала работы этого экземпляра bash.
И
Например:
Полный список временны́х зон на системах с
🛠 #bash
—
✅ @bashdays / @linuxfactory / @blog
date
для работы с датами/временем.Очень удобная команда, имеет очень много форматов и позволяет складывать/вычитать даты, например:
date -d"-1 day" # Чт 02 янв 2025 21:52:15 MSK - текущая дата минус один день.
date -d"+2 week" # Пт 17 янв 2025 21:53:48 MSK - текущая дата плюс две недели.
"day", "week" "month", "year", "hour", "min", "sec"
Но в bash есть еще средства для работы со временем:
ㅤ
Переменная
SECONDS
показывает, сколько секунд прошло с начала запуска скрипта или момента задания значения переменной. Обычно используется для хронометража блока кода скрипта. Например:SECONDS=0
# здесь блок длительного кода
echo $SECONDS
Переменная
EPOCHSECONDS
- показывает число секунд, прошедших с начала эпохи UNIX (01.01.1970 00:00:00 UTC).Обратите внимание, число секунд не зависит от часового пояса.
EPOCHREALTIME
- аналогична предыдущей, но секунды с точностью до микросекунды. С помощью этой переменной можно точно отслеживать время небольших кусков кода. Даже если просто вывести переменную дважды - будет разное время:echo $EPOCHREALTIME $EPOCHREALTIME
# 1744652451,166523 1744652451,166539
Обратите внимание, разделитель дробной части может быть различным, в зависимости от языковых настроек.
Переменные
EPOCHSECONDS
и EPOCHREALTIME
обнулить не получится.И еще есть специальный формат оператора
printf
для преобразования секунд UNIX в формат дат:printf '%(DT_FORMAT)T' $EPOCHSECONDS
DT_FORMAT
- практически полностью совпадает с форматом команды date
.Например:
printf '%(%Y%m%d-%H%M%S)T' $EPOCHSECONDS
# 20250414-203214
Если не указать переменную или указать -1 - будет использовано текущая дата/время. Если указать -2 - будет использовано время начала работы этого экземпляра bash.
printf
удобен тем, что выполняется гораздо быстрее чем date
(хотя говорить о скорости bash немного смешно) и позволяет результат операции записать сразу в переменную (Например DT).printf -v DT '%(%Y%m%d-%H%M%S)T'
И
date
и printf
работают в локальной временно́й зоне, чтобы это изменить можно задать "врéменную переменную" TZ.Например:
TZ='UTC' date
# Пн 14 апр 2025 16:15:57 UTC
TZ='Asia/Irkutsk' printf '%(%Y%m%d-%H%M%S)T\n'
# 20250415-001621
Полный список временны́х зон на системах с
systemd
можно получить с помощью команды timedatectl list-timezones
.—
Please open Telegram to view this post
VIEW IN TELEGRAM
Всё тебе, блядь, смехуюшечки да пиздахаханьки.
ㅤ
Создаём файл:
Внутри получаем:
И применяем бэд-практику:
Эта команда читает файл
Что тут не так?
А всё! В лучшем случае получишь хуем по лбу и примеришь золотой пизды колпак. Эта команда испортит файл. Низя так делать! Всё проебёшь!
После этой команды файл
А теперь делаем правильно!
Смотрим содержимое файла
Здесь мы всё сделали через временный файл, громоздко, но по крайней мере безопасно. Веселый колпак тебе теперь точно не светит.
Можно извратиться и провернуть всё это дело на основе дескрипторов, но опять же этот способ не безопасен.
Можно правда хакнуть таким методом:
Это работает без временного файла на уровне Bash, потому что
Резюмируем: Не ссы использовать временные файлы, пусть твои bash скрипты будут безопасны и читаемы.
🛠 #bash #badpractices #bestpractices
—
✅ @bashdays / @linuxfactory / @blog
ㅤ
Создаём файл:
echo -e "foo\nbar\nfoo again" > bashdays.txt
Внутри получаем:
foo
bar
foo again
И применяем бэд-практику:
cat bashdays.txt | sed 's/foo/baz/g' > bashdays.txt
Эта команда читает файл
bashdays.txt
и одновременно пишет в него.Что тут не так?
А всё! В лучшем случае получишь хуем по лбу и примеришь золотой пизды колпак. Эта команда испортит файл. Низя так делать! Всё проебёшь!
После этой команды файл
bashdays.txt
обнулится. Хотя визуально команда выглядит абсолютно безопасной.А теперь делаем правильно!
sed 's/foo/baz/g' bashdays.txt > tmpfile && mv tmpfile bashdays.txt
Смотрим содержимое файла
bashdays.txt
и видим ожидаемый результат:baz
bar
baz again
Здесь мы всё сделали через временный файл, громоздко, но по крайней мере безопасно. Веселый колпак тебе теперь точно не светит.
Можно извратиться и провернуть всё это дело на основе дескрипторов, но опять же этот способ не безопасен.
Можно правда хакнуть таким методом:
printf '%s\n' ',s/foo/baz/g' w q | ed -s bashdays.txt
Это работает без временного файла на уровне Bash, потому что
ed
сделаем всё сам. Но опять же конструкция нихуя непонятная. Резюмируем: Не ссы использовать временные файлы, пусть твои bash скрипты будут безопасны и читаемы.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Нежных много, деловых мало. Ну не могу я из песни слов выбросить, получится сухо и не интересно.
ㅤ
Поэтому нарушать традиций не будем, продолжаем в том же ключе. А нежные пусть идут на... ну ты понял.
Рассмотрим распространённый случай:
Тут всё предельно ясно и понятно. Все в ажуре!
Но это вершина айсберга. Эта команда может отрабатывать не так, как ты ожидаешь. Потому что
Что подразумевается по «хитрыми штуками»
— Разделить содержимое на отдельные слова (если там есть пробелы).
— Подставить имена файлов с таким шаблоном, если он выглядит как
И тут у новичков возникает многочасовой проёб, когда переменная выводит неправильные значения.
Смотри:
Выглядит опять всё красиво. А по факту получаешь:
Да блядь! А я просто хотел вывести строкой
Первое
Поэтому, если ты хочешь наверняка вывести переменную как есть, лучше используй `printf`
Для маленьких:
Представь, что ты говоришь падшей женщине: «покажи что у тебя в трусах», она снимает трусы, а там — большой сочный хуй.
А чтобы в трусах был ожидаемый результат, нужно изначально это учесть в моменте знакомства (до просьбы) и расставить все кавычки.
Хотя у каждого свой ожидаемый результат… возможно кавычки вовсе и не потребуются.
Такие дела. Изучай!
🛠 #bash #badpractices #bestpractices
—
✅ @bashdays / @linuxfactory / @blog
ㅤ
Поэтому нарушать традиций не будем, продолжаем в том же ключе. А нежные пусть идут на... ну ты понял.
Рассмотрим распространённый случай:
echo $foo
Тут всё предельно ясно и понятно. Все в ажуре!
Но это вершина айсберга. Эта команда может отрабатывать не так, как ты ожидаешь. Потому что
foo
это переменная. И если ты её не возьмешь в кавычки, то Bash может сделать с её содержимым всякие хитрые штуки.Что подразумевается по «хитрыми штуками»
— Разделить содержимое на отдельные слова (если там есть пробелы).
— Подставить имена файлов с таким шаблоном, если он выглядит как
*.zip
(это называется глоббинг).И тут у новичков возникает многочасовой проёб, когда переменная выводит неправильные значения.
Смотри:
msg="Пожалуйста, введите имя файла в формате *.zip"
echo $msg
Выглядит опять всё красиво. А по факту получаешь:
Пожалуйста, введите имя файла в формате awscliv2.zip
Да блядь! А я просто хотел вывести строкой
*.zip
а не получить список файлов в текущей папке.var="*.zip"
echo "$var"
echo $var
Первое
echo
напечатает *.zip
, а второе выведет список всех файлов, которые заканчиваются на .zip.Поэтому, если ты хочешь наверняка вывести переменную как есть, лучше используй `printf`
printf "%s\n" "$foo"
Для маленьких:
Представь, что ты говоришь падшей женщине: «покажи что у тебя в трусах», она снимает трусы, а там — большой сочный хуй.
А чтобы в трусах был ожидаемый результат, нужно изначально это учесть в моменте знакомства (до просьбы) и расставить все кавычки.
Хотя у каждого свой ожидаемый результат… возможно кавычки вовсе и не потребуются.
Такие дела. Изучай!
—
Please open Telegram to view this post
VIEW IN TELEGRAM