К основному содержанию
правило

bash — правило для Cursor: что делает и как установить

Правило задаёт стиль для Bash-скриптов: обработка ошибок, кавычки, переменные и структура кода. Подходит для проектов, где скрипты проходят через Cursor.

Установить в Cursor · Вручную: положить файлы Все способы и платформы ↓
.cursor/rules/bash.mdc
Открыть на GitHub

Что делает bash

Правило направляет Cursor к Bash-скриптам с #!/usr/bin/env bash и set -euo pipefail. Оно предлагает помещать логику в функции и main, объявлять локальные переменные через local, а глобальные константы писать в UPPER_SNAKE_CASE. Отдельно заданы отступы в 2 пробела и ориентир по длине строк около 80 символов.

В рекомендациях есть кавычки вокруг раскрытия переменных, массивы для списков, [[ ... ]] для условий, длинные опции команд и $(command) вместо обратных кавычек. Ошибки следует отправлять в STDERR, многострочный текст оформлять через heredoc, а временные файлы очищать с помощью trap. Использование [[ ... ]] означает, что правило ориентировано на Bash, а не на POSIX sh.

Файл с областью **/* задаёт эти правила для всех путей, к которым применяется Cursor. Для установки нужен путь .cursor/rules/bash.mdc в проекте.

Какие задачи решает

  • задать обработку ошибок в Bash-скрипте
  • разнести логику по функциям и main
  • защитить переменные от разбиения на слова
  • очистить временные файлы через trap
  • разделить обычный вывод и ошибки

Примеры запросов агенту

  • Проверь Bash-скрипт и приведи его к правилам из .cursor/rules/bash.mdc.
  • Перепиши этот скрипт: добавь set -euo pipefail, main, локальные переменные и безопасные кавычки.
  • Проверь обработку временных файлов, ошибок и многострочного текста в этом Bash-скрипте.

Как установить bash

Вручную: положить файлы

.cursor/rules/bash.mdc

Во frontmatter: description, globs, alwaysApply

По шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules

Вопросы о bash

Как установить bash в Cursor?

Добавьте файл .cursor/rules/bash.mdc в проект Cursor.

Что делает правило bash?

Оно задаёт практики для Bash: обработку ошибок, безопасную работу с переменными, структуру через функции и main, очистку ресурсов и оформление вывода.

Подходит ли bash для POSIX sh?

Правило ориентировано на Bash и использует конструкцию [[ ... ]], поэтому его рекомендации не рассчитаны на POSIX sh.

Исходный текст

bash.mdc · CC0-1.0
---
description: Enforces modern, robust, and maintainable bash scripting practices, focusing on error handling, quoting, variable management, and code organization.
globs: **/*
---
# bash Best Practices

This guide outlines the definitive best practices for writing bash scripts. Adhere to these rules to ensure your scripts are reliable, readable, and maintainable by the entire team.

## 1. Code Organization and Structure

### 1.1 Shebang and Interpreter Options
Always start scripts with `#!/usr/bin/env bash` for portability. Immediately follow with `set -euo pipefail` to ensure robust error handling.

*   `set -e` (errexit): Exit immediately if a command exits with a non-zero status.
*   `set -u` (nounset): Treat unset variables as an error and exit immediately.
*   `set -o pipefail`: The return value of a pipeline is the status of the last command to exit with a non-zero status, or zero if all commands exit successfully.

❌ BAD:
```bash
#!/bin/bash
# Missing error handling
```

✅ GOOD:
```bash
#!/usr/bin/env bash
set -euo pipefail

# Script logic here
```

### 1.2 File Header and Comments
Every script must begin with a descriptive header. Use clear, concise comments for functions and complex logic.

```bash
#!/usr/bin/env bash
set -euo pipefail

## my-script.sh
#
# Description: This script performs a critical system backup.
# It backs up configuration files and database dumps to a remote server.
#
# Usage: ./my-script.sh [--full | --incremental]
#
# Globals:
#   BACKUP_DIR
#   REMOTE_HOST
#
# Arguments:
#   --full: Perform a full backup.
#   --incremental: Perform an incremental backup.
#
# Returns:
#   0 on success, non-zero on error.
#
# Author: Your Name <[email protected]>
# Date: 2025-01-01
#
###############################################################################

# ... rest of the script
```

### 1.3 Functions and `main` Entry Point
Encapsulate all script logic within functions. Use a `main` function as the primary entry point. This improves readability, reusability, and variable scoping.

❌ BAD:
```bash
#!/usr/bin/env bash
set -euo pipefail
# Script logic directly in the global scope
echo "Starting operation..."
ls -l /tmp
# ...
```

✅ GOOD:
```bash
#!/usr/bin/env bash
set -euo pipefail

# ... file header ...

# Performs a specific sub-task.
# Arguments:
#   $1 - The item to process.
process_item() {
  local item="${1}"
  echo "Processing: ${item}"
  # ...
}

# Main entry point for the script.
# Arguments:
#   $@ - All command-line arguments.
main() {
  echo "Script started."
  for arg in "$@"; do
    process_item "${arg}"
  done
  echo "Script finished."
}

# Call the main function with all script arguments.
main "$@"
```

### 1.4 Variable Scoping and Naming
Declare variables with `local` inside functions. Use `UPPER_SNAKE_CASE` for global `readonly` constants and `lower_snake_case` for local variables and function names.

❌ BAD:
```bash
#!/usr/bin/env bash
set -euo pipefail

GLOBAL_VAR="value" # Not readonly, could be modified
my_func() {
  temp_var="another_value" # Not local, pollutes global scope
}
```

✅ GOOD:
```bash
#!/usr/bin/env bash
set -euo pipefail

readonly CONFIG_FILE="/etc/my_app/config.conf" # Global constant
readonly LOG_LEVEL="INFO"

my_function() {
  local temp_message="This is a local message."
  echo "${LOG_LEVEL}: ${temp_message}"
  # ...
}

main() {
  my_function
}

main "$@"
```

### 1.5 Indentation and Line Length
Use 2 spaces for indentation. Limit lines to approximately 80 characters. Break long lines with backslashes `\` for readability.

❌ BAD:
```bash
if [[ "${long_variable_name_one}" == "${long_variable_name_two}" && "${another_long_variable}" -gt 100 ]]; then echo "This line is way too long and hard to read."; fi
```

✅ GOOD:
```bash
if [[ "${long_variable_name_one}" == "${long_variable_name_two}" && \
      "${another_long_variable}" -gt 100 ]]; then
  echo "This line is readable."
fi
```

### 1.6 Cleanup with `trap`
Use `trap` to ensure resources (e.g., temporary files) are cleaned up even if the script exits unexpectedly.

```bash
#!/usr/bin/env bash
set -euo pipefail

readonly TMP_DIR="$(mktemp -d)"

cleanup() {
  echo "Cleaning up temporary directory: ${TMP_DIR}" >&2
  rm -rf "${TMP_DIR}"
}

# Trap EXIT, INT (Ctrl+C), and TERM signals to run cleanup
trap cleanup EXIT INT TERM

main() {
  echo "Working in temporary directory: ${TMP_DIR}"
  touch "${TMP_DIR}/temp_file.txt"
  # ... script logic ...
  # No need to explicitly call cleanup, trap handles it.
}

main "$@"
```

## 2. Common Patterns and Anti-patterns

### 2.1 Always Quote Variables and Command Substitutions
This is the single most important rule. Always double-quote variable expansions (`"${var}"`) and use `$(command)` for command substitution to prevent word splitting and globbing.

❌ BAD:
```bash
files="file1.txt file with spaces.txt"
for f in $files; do # Word splitting occurs
  echo "Processing: $f" # Unquoted, will cause issues with spaces/globs
done

output=`ls -l` # Deprecated backticks
```

✅ GOOD:
```bash
files=("file1.txt" "file with spaces.txt") # Use arrays for lists
for f in "${files[@]}"; do # Correctly iterates over array elements
  echo "Processing: \"${f}\"" # Quoted, handles spaces correctly
done

output=$(ls -l) # Modern command substitution
```

### 2.2 Prefer `[[ ... ]]` for Conditionals
Use the bash-specific `[[ ... ]]` construct over `[ ... ]` (test). `[[ ... ]]` is safer, handles quoting internally, and supports advanced features like regex matching (`=~`).

❌ BAD:
```bash
if [ "$my_var" = "value" ]; then # Prone to issues if my_var is empty or contains spaces
  echo "Legacy test"
fi
```

✅ GOOD:
```bash
if [[ "${my_var}" == "value" ]]; then # Safer, quoting generally recommended for clarity
  echo "Modern test"
fi

# Regex matching
if [[ "${filename}" =~ \.log$ ]]; then
  echo "It's a log file."
fi
```

### 2.3 Use Long Options for Readability
Prefer long-form command options (`--recursive`) over short-form (`-r`) in scripts for improved readability.

❌ BAD:
```bash
rm -rf "${dir}"
```

✅ GOOD:
```bash
rm --recursive --force -- "${dir}" # -- to separate options from arguments
```

### 2.4 Redirect Errors to `STDERR`
Ensure all error messages and diagnostic output go to `STDERR` (`>&2`), reserving `STDOUT` for the intended program output.

```bash
log_error() {
  printf "[ERROR] %s: %s\n" "$(date '+%Y-%m-%dT%H:%M:%S%z')" "${*}" >&2
}

if ! some_command; then
  log_error "Failed to execute some_command."
  exit 1
fi
```

### 2.5 Heredocs for Multi-line Strings
Use heredocs for multi-line strings. Quote the tag (`<<'EOF'`) to prevent variable expansion and command substitution within the heredoc.

❌ BAD:
```bash
echo "Hello ${USER},"
echo "This is a multi-line message."
echo "Current date: $(date)"
```

✅ GOOD (Literal):
```bash
cat <<'EOF'
Hello ${USER},
This is a literal multi-line message.
Current date: $(date)
EOF
```

✅ GOOD (Interpolated):
```bash
cat <<EOF
Hello ${USER},
This is an interpolated multi-line message.
Current date: $(date)
EOF
```

### 2.6 Arithmetic with `(( ... ))`
Use `(( ... ))` for arithmetic operations. It's cleaner and safer than `expr` or `let`.

❌ BAD:
```bash
COUNT=`expr $COUNT + 1`
let COUNT=COUNT+1
```

✅ GOOD:
```bash
count=0
((count++))
echo "${count}" # Output: 1

num_a=10
num_b=5
result=$((num_a * num_b))
echo "${result}" # Output: 50
```

### 2.7 Scoped Directory Changes
When changing directories, use a subshell `(cd ...)` or `pushd`/`popd` to ensure the change is temporary and doesn't affect the rest of the script.

❌ BAD:
```bash
cd /tmp/my_app
# ... operations ...
cd - # Easy to forget, or fail if previous dir is gone
```

✅ GOOD:
```bash
(
  cd /tmp/my_app || exit 1 # Subshell, changes only apply here
  echo "Current directory in subshell: $(pwd)"
  # ... operations ...
)
echo "Current directory outside subshell: $(pwd)" # Original directory
```

## 3. Common Pitfalls and Gotchas

### 3.1 `while read` in a Pipe
Variables set inside a `while read` loop that is part of a pipeline will not persist outside the loop, as the loop runs in a subshell.

❌ BAD:
```bash
count=0
ls | while read -r file; do
  ((count++)) # count is modified in a subshell
done
echo "Total files: ${count}" # Will likely be 0
```

✅ GOOD:
```bash
count=0
# Use process substitution or redirect file directly
while read -r file; do
  ((count++))
done < <(ls) # Process substitution
echo "Total files: ${count}" # Correct count

# Alternative: mapfile (Bash 4+)
mapfile -t files_array < <(ls)
count="${#files_array[@]}"
echo "Total files: ${count}"
```

### 3.2 `sudo` with Redirection
Redirection (`>`) happens *before* `sudo` executes the command. To write to a root-owned file, run the entire command under `sudo`.

❌ BAD:
```bash
echo "Sensitive data" > /root/protected_file # Redirection by current user
```

✅ GOOD:
```bash
echo "Sensitive data" | sudo tee /root/protected_file > /dev/null
# OR
sudo bash -c 'echo "Sensitive data" > /root/protected_file'
```

### 3.3 Avoid `eval`
`eval` is a security risk and makes scripts hard to debug. Avoid it unless absolutely necessary and you fully control the input.

❌ BAD:
```bash
user_input="rm -rf /"
eval "${user_input}" # Dangerous!
```

✅ GOOD:
```bash
# Refactor to avoid eval. Use case statements, arrays, or functions instead.
# If dynamic command execution is truly needed, validate and sanitize input rigorously.
```

## 4. Testing Approaches

### 4.1 `shellcheck`
Integrate `shellcheck` into your workflow. It's an invaluable static analysis tool that catches common pitfalls and warns about bad practices.

```bash
# Run shellcheck on your script
shellcheck myscript.sh
```

### 4.2 Debugging with `set -x`
Use `set -x` (xtrace) for debugging. It prints each command and its arguments after expansion. Localize its use to specific sections.

```bash
#!/usr/bin/env bash
set -euo pipefail

my_debug_function() {
  set -x # Start tracing
  local debug_var="hello"
  echo "Debug var: ${debug_var}"
  set +x # Stop tracing
}

main() {
  echo "Before debug function."
  my_debug_function
  echo "After debug function."
}

main "$@"
```

### 4.3 Syntax Check with `bash -n`
Before running, perform a dry run to check for syntax errors.

```bash
bash -n myscript.sh
```

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Похожие правила IDE

Все правила IDE по теме «Языки программирования» →
bash-scripting Mindrally Скилл задаёт агенту правила написания Bash-скриптов: валидация ввода, обработка ошибок, переносимость. Пригодится, когда агент пишет деплой, бэкапы или cron-задачи. CX Codex +1 875установок bash-master JosiahSiegel Помогает писать и проверять Bash-скрипты с учётом ShellCheck, защитных флагов и совместимости с Linux, macOS, WSL и контейнерами. CX Codex +1 459установок bash-linux davila7 Справочник по Bash для macOS и Linux: связки команд, работа с файлами и процессами, обработка ошибок. Нужен, когда агент правит скрипты или разбирается с логами. 215установок bash-script-validator akin-ozer Скилл прогоняет bash и POSIX-скрипты через синтаксическую проверку, ShellCheck и собственные проверки безопасности. Пригодится перед CI. CX Codex +1 679установок bash-script-generator akin-ozer Скилл, который превращает задачу в готовый bash-скрипт: собирает требования, пишет код по шаблону и проверяет его. CX Codex +1 670установок shell официальный github Правило, которое заставляет GitHub Copilot писать чистые и безопасные shell-скрипты. Применяется к файлам *.sh автоматически. ★ 40 478звёзд репо

Из того же набора240

Весь набор →
boto3 Направляет ассистента писать надёжный код на Python с boto3: переиспользовать клиенты, разбивать запросы на пачки и выбирать готовые пагинаторы вместо ручных циклов. ★ 3 580звёзд репо black Правило для Cursor задаёт единый стиль Python-кода с помощью Black. Оно помогает согласовать форматирование исходников и проверять его перед слиянием изменений. ★ 3 580звёзд репо behave Правило задаёт Cursor стандарты для BDD-тестов на behave: тонкие шаги, чистый Gherkin, фикстуры через environment.py. ★ 3 580звёзд репо beautifulsoup4 Задаёт стандарты парсинга HTML на Python: выбор lxml, работа с CSS-селекторами и валидация структур через Pydantic. ★ 3 580звёзд репо azure Правило для Cursor с набором требований к коду и инфраструктуре в Azure: IaC, безопасность, экономия ресурсов. Пригодится, если проект живёт в Azure. ★ 3 580звёзд репо azure-pipelines Задаёт правила написания YAML-пайплайнов для Azure DevOps: многостадийные сборки, шаблоны, кеширование и безопасность секретов. ★ 3 580звёзд репо axios Задаёт ИИ-агенту в Cursor единый стиль работы с axios: общий инстанс, модули API, перехватчики и отмена запросов. Пригодится, когда компоненты уже пестрят разными вызовами. ★ 3 580звёзд репо aws Задаёт агенту стандарты разработки на AWS: только CDK v2, переиспользование окружения Lambda, идемпотентность и минимальные права IAM. ★ 3 580звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой