@hybridlabor-api/aos 4.8.0 → 4.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/{agents.md → AGENTS.md} +3 -1
- package/.agents/nodes.json +3 -1
- package/.agents/vendor-manifest.json +23 -1
- package/.claude/agents/godmode-media-eventtech.md +1 -1
- package/.claude/hooks/conventional-commits.mjs +125 -0
- package/.claude/hooks/env-file-protection.mjs +105 -0
- package/.claude/hooks/go-gate.mjs +101 -81
- package/.claude/hooks/memb-inject.mjs +29 -1
- package/.claude/settings.json +13 -0
- package/.claude/workflows/startcycle-dispatch.mjs +23 -1
- package/.opencode/agents/godmode-media-eventtech.md +1 -1
- package/.opencode/plugins/bdb-aos.js +31 -4
- package/CLAUDE.md +0 -571
- package/README.de.md +1 -1
- package/README.md +1 -1
- package/README.pt.md +1 -1
- package/THIRD_PARTY_NOTICES.md +126 -0
- package/bin/aos-doctor.mjs +1 -1
- package/docs/skills_table.md +1 -1
- package/installer.js +187 -55
- package/package.json +7 -3
- package/packages/aos-cli/README.md +80 -0
- package/packages/aos-cli/bin/aos-cli.mjs +134 -0
- package/packages/aos-cli/core-skills.json +12 -0
- package/packages/aos-cli/extensions/aos.ts +321 -0
- package/packages/aos-cli/package-lock.json +1923 -0
- package/packages/aos-cli/package.json +29 -0
- package/packages/aos-cli/scripts/check-theme.mjs +63 -0
- package/packages/aos-cli/themes/aos.json +97 -0
- package/scripts/build-plugin-manifest.mjs +131 -0
- package/scripts/validate-skills.mjs +81 -6
- package/skills/basic/ao-orchestrator/SKILL.md +116 -0
- package/skills/basic/bdb-eventagency-skill/SKILL.md +252 -0
- package/skills/basic/bdb-shipping-skill/SKILL.md +161 -0
- package/skills/basic/godmode-eventtech/SKILL.md +4 -1
- package/skills/global_config/agenttrail/SKILL.md +6 -1
- package/skills/global_config/aos-project-init/SKILL.md +2 -0
- package/skills/global_config/aos-project-init/assets/AGENTS.template.md +1 -1
- package/skills/global_config/aos-project-init/scripts/aos-project-doctor.mjs +1 -1
- package/skills/global_config/aos-setup/SKILL.md +1 -1
- package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +1 -1
- package/skills/global_config/ask-tim/SKILL.md +7 -7
- package/skills/global_config/bash-script-generator/SKILL.md +201 -0
- package/skills/global_config/bash-script-generator/assets/templates/standard-template.sh +96 -0
- package/skills/global_config/bash-script-generator/docs/bash-scripting-guide.md +729 -0
- package/skills/global_config/bash-script-generator/docs/generation-best-practices.md +193 -0
- package/skills/global_config/bash-script-generator/docs/script-patterns.md +566 -0
- package/skills/global_config/bash-script-generator/docs/text-processing-guide.md +437 -0
- package/skills/global_config/bash-script-generator/examples/log-analyzer.sh +92 -0
- package/skills/global_config/bash-script-generator/scripts/generate_script_template.sh +123 -0
- package/skills/global_config/bash-script-generator/scripts/run_ci_checks.sh +172 -0
- package/skills/global_config/bash-script-generator/scripts/test_generator.sh +413 -0
- package/skills/global_config/bash-script-validator/SKILL.md +249 -0
- package/skills/global_config/bash-script-validator/docs/awk-reference.md +449 -0
- package/skills/global_config/bash-script-validator/docs/bash-reference.md +468 -0
- package/skills/global_config/bash-script-validator/docs/common-mistakes.md +623 -0
- package/skills/global_config/bash-script-validator/docs/grep-reference.md +395 -0
- package/skills/global_config/bash-script-validator/docs/regex-reference.md +391 -0
- package/skills/global_config/bash-script-validator/docs/sed-reference.md +454 -0
- package/skills/global_config/bash-script-validator/docs/shell-reference.md +463 -0
- package/skills/global_config/bash-script-validator/docs/shellcheck-reference.md +399 -0
- package/skills/global_config/bash-script-validator/examples/bad-bash.sh +55 -0
- package/skills/global_config/bash-script-validator/examples/bad-shell.sh +54 -0
- package/skills/global_config/bash-script-validator/examples/good-bash.sh +71 -0
- package/skills/global_config/bash-script-validator/examples/good-shell.sh +69 -0
- package/skills/global_config/bash-script-validator/scripts/run_ci_checks.sh +23 -0
- package/skills/global_config/bash-script-validator/scripts/shellcheck_wrapper.sh +174 -0
- package/skills/global_config/bash-script-validator/scripts/test_validate.sh +446 -0
- package/skills/global_config/bash-script-validator/scripts/validate.sh +512 -0
- package/skills/global_config/ci-pipeline/SKILL.md +135 -0
- package/skills/global_config/deja-memory/SKILL.md +3 -1
- package/skills/global_config/dispatching-parallel-agents/SKILL.md +170 -0
- package/skills/global_config/dockerfile-generator/SKILL.md +1038 -0
- package/skills/global_config/dockerfile-generator/examples/example.dockerignore +95 -0
- package/skills/global_config/dockerfile-generator/examples/golang-distroless.Dockerfile +34 -0
- package/skills/global_config/dockerfile-generator/examples/java-springboot.Dockerfile +45 -0
- package/skills/global_config/dockerfile-generator/examples/nextjs-production.Dockerfile +49 -0
- package/skills/global_config/dockerfile-generator/examples/nodejs-multistage.Dockerfile +55 -0
- package/skills/global_config/dockerfile-generator/examples/python-fastapi.Dockerfile +48 -0
- package/skills/global_config/dockerfile-generator/references/language_specific_guides.md +510 -0
- package/skills/global_config/dockerfile-generator/references/multistage_builds.md +570 -0
- package/skills/global_config/dockerfile-generator/references/optimization_patterns.md +492 -0
- package/skills/global_config/dockerfile-generator/references/security_best_practices.md +375 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_dockerignore.sh +199 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_golang.sh +172 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_java.sh +185 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_nodejs.sh +279 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_python.sh +218 -0
- package/skills/global_config/dockerfile-generator/scripts/test_generator.sh +210 -0
- package/skills/global_config/dockerfile-validator/SKILL.md +300 -0
- package/skills/global_config/dockerfile-validator/examples/.dockerignore.example +34 -0
- package/skills/global_config/dockerfile-validator/examples/bad-example.Dockerfile +37 -0
- package/skills/global_config/dockerfile-validator/examples/golang-distroless.Dockerfile +50 -0
- package/skills/global_config/dockerfile-validator/examples/good-example.Dockerfile +52 -0
- package/skills/global_config/dockerfile-validator/examples/python-optimized.Dockerfile +53 -0
- package/skills/global_config/dockerfile-validator/examples/security-issues.Dockerfile +42 -0
- package/skills/global_config/dockerfile-validator/references/docker_best_practices.md +348 -0
- package/skills/global_config/dockerfile-validator/references/optimization_guide.md +473 -0
- package/skills/global_config/dockerfile-validator/references/security_checklist.md +208 -0
- package/skills/global_config/dockerfile-validator/scripts/dockerfile-validate.sh +699 -0
- package/skills/global_config/dockerfile-validator/scripts/test_validate.sh +35 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn-lock-read.Dockerfile +6 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn.Dockerfile +6 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/from-platform-nonroot.Dockerfile +7 -0
- package/skills/global_config/dockerfile-validator/tests/test_regression.sh +164 -0
- package/skills/global_config/finishing-a-development-branch/SKILL.md +228 -0
- package/skills/global_config/github-actions-generator/SKILL.md +353 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/composite/action.yml +82 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/Dockerfile +25 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/action.yml +42 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/entrypoint.sh +27 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/action.yml +33 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/index.js +50 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/package.json +27 -0
- package/skills/global_config/github-actions-generator/assets/templates/workflow/basic_workflow.yml +242 -0
- package/skills/global_config/github-actions-generator/assets/templates/workflow/reusable_workflow.yml +106 -0
- package/skills/global_config/github-actions-generator/examples/README.md +147 -0
- package/skills/global_config/github-actions-generator/examples/actions/setup-node-cached/action.yml +93 -0
- package/skills/global_config/github-actions-generator/examples/caching/docker-buildkit.yml +256 -0
- package/skills/global_config/github-actions-generator/examples/security/dependency-review.yml +62 -0
- package/skills/global_config/github-actions-generator/examples/security/sbom-attestation.yml +119 -0
- package/skills/global_config/github-actions-generator/examples/triggers/chatops-commands.yml +475 -0
- package/skills/global_config/github-actions-generator/examples/triggers/repository-dispatch.yml +418 -0
- package/skills/global_config/github-actions-generator/examples/triggers/workflow-orchestration.yml +404 -0
- package/skills/global_config/github-actions-generator/examples/workflows/docker-build-push.yml +68 -0
- package/skills/global_config/github-actions-generator/examples/workflows/go-ci.yml +161 -0
- package/skills/global_config/github-actions-generator/examples/workflows/monorepo-ci.yml +340 -0
- package/skills/global_config/github-actions-generator/examples/workflows/multi-environment-deploy.yml +406 -0
- package/skills/global_config/github-actions-generator/examples/workflows/nodejs-ci.yml +122 -0
- package/skills/global_config/github-actions-generator/examples/workflows/python-ci.yml +157 -0
- package/skills/global_config/github-actions-generator/examples/workflows/scheduled-tasks.yml +376 -0
- package/skills/global_config/github-actions-generator/references/advanced-triggers.md +917 -0
- package/skills/global_config/github-actions-generator/references/best-practices.md +755 -0
- package/skills/global_config/github-actions-generator/references/common-actions.md +715 -0
- package/skills/global_config/github-actions-generator/references/custom-actions.md +320 -0
- package/skills/global_config/github-actions-generator/references/expressions-and-contexts.md +688 -0
- package/skills/global_config/github-actions-generator/references/modern-features.md +421 -0
- package/skills/global_config/github-actions-generator/scripts/test_generator.sh +344 -0
- package/skills/global_config/github-actions-templates/SKILL.md +7 -0
- package/skills/global_config/github-actions-validator/SKILL.md +576 -0
- package/skills/global_config/github-actions-validator/examples/README.md +88 -0
- package/skills/global_config/github-actions-validator/examples/outdated-versions.yml +76 -0
- package/skills/global_config/github-actions-validator/examples/valid-ci.yml +79 -0
- package/skills/global_config/github-actions-validator/examples/with-errors.yml +47 -0
- package/skills/global_config/github-actions-validator/references/act_usage.md +233 -0
- package/skills/global_config/github-actions-validator/references/action_versions.md +122 -0
- package/skills/global_config/github-actions-validator/references/actionlint_usage.md +343 -0
- package/skills/global_config/github-actions-validator/references/common_errors.md +512 -0
- package/skills/global_config/github-actions-validator/references/modern_features.md +384 -0
- package/skills/global_config/github-actions-validator/references/runners.md +317 -0
- package/skills/global_config/github-actions-validator/scripts/install_tools.sh +113 -0
- package/skills/global_config/github-actions-validator/scripts/validate_workflow.sh +910 -0
- package/skills/global_config/github-actions-validator/tests/test_validate_workflow.sh +237 -0
- package/skills/global_config/makefile-generator/SKILL.md +614 -0
- package/skills/global_config/makefile-generator/assets/templates/.gitkeep +1 -0
- package/skills/global_config/makefile-generator/docs/makefile-structure.md +530 -0
- package/skills/global_config/makefile-generator/docs/optimization-guide.md +784 -0
- package/skills/global_config/makefile-generator/docs/patterns-guide.md +642 -0
- package/skills/global_config/makefile-generator/docs/security-guide.md +361 -0
- package/skills/global_config/makefile-generator/docs/targets-guide.md +642 -0
- package/skills/global_config/makefile-generator/docs/variables-guide.md +596 -0
- package/skills/global_config/makefile-generator/scripts/add_standard_targets.sh +539 -0
- package/skills/global_config/makefile-generator/scripts/generate_makefile_template.sh +690 -0
- package/skills/global_config/makefile-generator/test/test_helper_scripts.sh +190 -0
- package/skills/global_config/makefile-validator/SKILL.md +244 -0
- package/skills/global_config/makefile-validator/docs/bake-tool.md +1000 -0
- package/skills/global_config/makefile-validator/docs/best-practices.md +858 -0
- package/skills/global_config/makefile-validator/docs/common-mistakes.md +944 -0
- package/skills/global_config/makefile-validator/examples/bad-makefile.mk +77 -0
- package/skills/global_config/makefile-validator/examples/good-makefile.mk +103 -0
- package/skills/global_config/makefile-validator/scripts/test_validate.sh +382 -0
- package/skills/global_config/makefile-validator/scripts/validate_makefile.sh +712 -0
- package/skills/global_config/{MCP_Manage → mcp-manage}/SKILL.md +3 -3
- package/skills/global_config/plan-canvas/SKILL.md +9 -2
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/ui.js +10 -2
- package/skills/global_config/plan-canvas/scripts/plan-canvas.js +1 -1
- package/skills/global_config/read-the-damn-docs/SKILL.md +175 -0
- package/skills/global_config/requesting-code-review/SKILL.md +98 -0
- package/skills/global_config/requesting-code-review/code-reviewer.md +198 -0
- package/skills/global_config/using-git-worktrees/SKILL.md +170 -0
- package/skills/global_config/verification-before-completion/SKILL.md +123 -0
- package/skills/global_config/writing-plans/SKILL.md +126 -46
- package/skills/global_config/writing-plans-legacy/SKILL.md +152 -0
- package/.claude/CLAUDE.md +0 -12
- package/mcps/RhinoMCP/docs/content/docs/getting-started/gemini.md +0 -61
- /package/{GEMINI.md → RULES.md} +0 -0
|
@@ -0,0 +1,623 @@
|
|
|
1
|
+
# Common Shell Scripting Mistakes
|
|
2
|
+
|
|
3
|
+
This guide covers frequent mistakes made in bash and shell scripts, their consequences, and how to fix them.
|
|
4
|
+
|
|
5
|
+
## 1. Unquoted Variables
|
|
6
|
+
|
|
7
|
+
### Problem
|
|
8
|
+
```bash
|
|
9
|
+
# Wrong
|
|
10
|
+
file=/path/with spaces/file.txt
|
|
11
|
+
cat $file # Breaks into multiple arguments
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Consequence
|
|
15
|
+
Word splitting and glob expansion cause unexpected behavior.
|
|
16
|
+
|
|
17
|
+
### Solution
|
|
18
|
+
```bash
|
|
19
|
+
# Right
|
|
20
|
+
file="/path/with spaces/file.txt"
|
|
21
|
+
cat "$file"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Rule
|
|
25
|
+
**Always quote variable expansions** unless you explicitly need word splitting.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 2. Not Checking Command Success
|
|
30
|
+
|
|
31
|
+
### Problem
|
|
32
|
+
```bash
|
|
33
|
+
# Wrong
|
|
34
|
+
cd /some/directory
|
|
35
|
+
rm -rf * # DANGEROUS if cd fails!
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Consequence
|
|
39
|
+
Commands execute even if previous commands fail, potentially catastrophic.
|
|
40
|
+
|
|
41
|
+
### Solution
|
|
42
|
+
```bash
|
|
43
|
+
# Right
|
|
44
|
+
cd /some/directory || exit 1
|
|
45
|
+
rm -rf *
|
|
46
|
+
|
|
47
|
+
# Or use set -e
|
|
48
|
+
set -e
|
|
49
|
+
cd /some/directory
|
|
50
|
+
rm -rf *
|
|
51
|
+
|
|
52
|
+
# Or check explicitly
|
|
53
|
+
if ! cd /some/directory; then
|
|
54
|
+
echo "Failed to change directory" >&2
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
rm -rf *
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 3. Using [ ] with Bash Features
|
|
63
|
+
|
|
64
|
+
### Problem
|
|
65
|
+
```bash
|
|
66
|
+
# Wrong (== not POSIX, may fail in sh)
|
|
67
|
+
if [ "$var" == "value" ]; then
|
|
68
|
+
echo "match"
|
|
69
|
+
fi
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Solution
|
|
73
|
+
```bash
|
|
74
|
+
# POSIX sh - use single =
|
|
75
|
+
if [ "$var" = "value" ]; then
|
|
76
|
+
echo "match"
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Or use bash [[ ]] (bash only)
|
|
80
|
+
if [[ "$var" == "value" ]]; then
|
|
81
|
+
echo "match"
|
|
82
|
+
fi
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 4. Useless Use of cat (UUOC)
|
|
88
|
+
|
|
89
|
+
### Problem
|
|
90
|
+
```bash
|
|
91
|
+
# Wrong - unnecessary cat
|
|
92
|
+
cat file.txt | grep pattern
|
|
93
|
+
cat file.txt | awk '{print $1}'
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Consequence
|
|
97
|
+
Wastes a process, less efficient.
|
|
98
|
+
|
|
99
|
+
### Solution
|
|
100
|
+
```bash
|
|
101
|
+
# Right
|
|
102
|
+
grep pattern file.txt
|
|
103
|
+
awk '{print $1}' file.txt
|
|
104
|
+
|
|
105
|
+
# Or use redirection
|
|
106
|
+
< file.txt grep pattern
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 5. Not Using -r with read
|
|
112
|
+
|
|
113
|
+
### Problem
|
|
114
|
+
```bash
|
|
115
|
+
# Wrong
|
|
116
|
+
while read line; do
|
|
117
|
+
echo "$line"
|
|
118
|
+
done < file
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Consequence
|
|
122
|
+
Backslashes are interpreted, leading character may be removed.
|
|
123
|
+
|
|
124
|
+
### Solution
|
|
125
|
+
```bash
|
|
126
|
+
# Right
|
|
127
|
+
while IFS= read -r line; do
|
|
128
|
+
echo "$line"
|
|
129
|
+
done < file
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
- `-r` prevents backslash interpretation
|
|
133
|
+
- `IFS=` prevents leading/trailing whitespace trimming
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 6. Testing $? After Multiple Commands
|
|
138
|
+
|
|
139
|
+
### Problem
|
|
140
|
+
```bash
|
|
141
|
+
# Wrong
|
|
142
|
+
command1
|
|
143
|
+
command2
|
|
144
|
+
if [ $? -eq 0 ]; then # Tests command2, not command1!
|
|
145
|
+
echo "Success"
|
|
146
|
+
fi
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Solution
|
|
150
|
+
```bash
|
|
151
|
+
# Right - test immediately
|
|
152
|
+
command1
|
|
153
|
+
if [ $? -eq 0 ]; then
|
|
154
|
+
echo "command1 succeeded"
|
|
155
|
+
fi
|
|
156
|
+
|
|
157
|
+
# Better - test directly
|
|
158
|
+
if command1; then
|
|
159
|
+
echo "Success"
|
|
160
|
+
fi
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 7. Arrays in POSIX sh Scripts
|
|
166
|
+
|
|
167
|
+
### Problem
|
|
168
|
+
```bash
|
|
169
|
+
#!/bin/sh
|
|
170
|
+
# Wrong - arrays not in POSIX sh
|
|
171
|
+
array=(one two three)
|
|
172
|
+
echo "${array[0]}"
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Solution
|
|
176
|
+
```bash
|
|
177
|
+
# Use bash
|
|
178
|
+
#!/bin/bash
|
|
179
|
+
array=(one two three)
|
|
180
|
+
echo "${array[0]}"
|
|
181
|
+
|
|
182
|
+
# Or use POSIX alternatives
|
|
183
|
+
set -- one two three
|
|
184
|
+
echo "$1"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 8. Not Declaring Functions Before Use
|
|
190
|
+
|
|
191
|
+
### Problem
|
|
192
|
+
```bash
|
|
193
|
+
# Wrong - function not defined yet
|
|
194
|
+
my_function
|
|
195
|
+
|
|
196
|
+
my_function() {
|
|
197
|
+
echo "Hello"
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Solution
|
|
202
|
+
```bash
|
|
203
|
+
# Right - define first
|
|
204
|
+
my_function() {
|
|
205
|
+
echo "Hello"
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
my_function
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 9. Using eval Unsafely
|
|
214
|
+
|
|
215
|
+
### Problem
|
|
216
|
+
```bash
|
|
217
|
+
# DANGEROUS
|
|
218
|
+
user_input="$1"
|
|
219
|
+
eval "$user_input" # Command injection risk!
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Consequence
|
|
223
|
+
Security vulnerability - arbitrary code execution.
|
|
224
|
+
|
|
225
|
+
### Solution
|
|
226
|
+
```bash
|
|
227
|
+
# Avoid eval when possible
|
|
228
|
+
# If necessary, sanitize input thoroughly
|
|
229
|
+
# Or use safer alternatives
|
|
230
|
+
|
|
231
|
+
# Example: dynamic variable names
|
|
232
|
+
var_name="my_var"
|
|
233
|
+
# Don't: eval "echo \$$var_name"
|
|
234
|
+
# Do: Use indirect expansion (bash)
|
|
235
|
+
echo "${!var_name}"
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## 10. Forgetting set -u
|
|
241
|
+
|
|
242
|
+
### Problem
|
|
243
|
+
```bash
|
|
244
|
+
# Wrong - typo goes unnoticed
|
|
245
|
+
nmae="John" # Typo
|
|
246
|
+
echo "Hello, $name" # Prints "Hello, " (empty)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Solution
|
|
250
|
+
```bash
|
|
251
|
+
# Right - use set -u
|
|
252
|
+
set -u
|
|
253
|
+
nmae="John" # Typo
|
|
254
|
+
echo "Hello, $name" # Error: name: unbound variable
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## 11. Incorrect String Comparison
|
|
260
|
+
|
|
261
|
+
### Problem
|
|
262
|
+
```bash
|
|
263
|
+
# Wrong - numeric comparison on strings
|
|
264
|
+
if [ "$version" -gt "2.0" ]; then
|
|
265
|
+
echo "New version"
|
|
266
|
+
fi
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Solution
|
|
270
|
+
```bash
|
|
271
|
+
# Right - string comparison
|
|
272
|
+
if [ "$version" = "2.0" ]; then
|
|
273
|
+
echo "Exact match"
|
|
274
|
+
fi
|
|
275
|
+
|
|
276
|
+
# Or use proper version comparison
|
|
277
|
+
if [[ "$version" > "2.0" ]]; then
|
|
278
|
+
echo "Greater"
|
|
279
|
+
fi
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## 12. Not Handling Spaces in Filenames
|
|
285
|
+
|
|
286
|
+
### Problem
|
|
287
|
+
```bash
|
|
288
|
+
# Wrong
|
|
289
|
+
for file in $(ls *.txt); do
|
|
290
|
+
echo "$file"
|
|
291
|
+
done
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Consequence
|
|
295
|
+
Files with spaces break into multiple items.
|
|
296
|
+
|
|
297
|
+
### Solution
|
|
298
|
+
```bash
|
|
299
|
+
# Right - use glob directly
|
|
300
|
+
for file in *.txt; do
|
|
301
|
+
echo "$file"
|
|
302
|
+
done
|
|
303
|
+
|
|
304
|
+
# Or use find with -print0
|
|
305
|
+
while IFS= read -r -d '' file; do
|
|
306
|
+
echo "$file"
|
|
307
|
+
done < <(find . -name "*.txt" -print0)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## 13. Backticks Instead of $()
|
|
313
|
+
|
|
314
|
+
### Problem
|
|
315
|
+
```bash
|
|
316
|
+
# Deprecated
|
|
317
|
+
result=`command arg1 arg2`
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Solution
|
|
321
|
+
```bash
|
|
322
|
+
# Modern
|
|
323
|
+
result=$(command arg1 arg2)
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Why
|
|
327
|
+
- Better nesting: `$(cmd1 $(cmd2))`
|
|
328
|
+
- Better readability
|
|
329
|
+
- Fewer escaping issues
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## 14. Using = Instead of == in [[ ]]
|
|
334
|
+
|
|
335
|
+
Not really a mistake, but inconsistent:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
# Both work in [[ ]]
|
|
339
|
+
[[ "$var" = "value" ]] # POSIX style (works)
|
|
340
|
+
[[ "$var" == "value" ]] # Bash style (also works)
|
|
341
|
+
|
|
342
|
+
# Only = works in [ ]
|
|
343
|
+
[ "$var" = "value" ] # Works
|
|
344
|
+
[ "$var" == "value" ] # May fail in POSIX sh
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**Recommendation**: Use `=` for portability, or stick to `==` in bash with `[[ ]]`.
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## 15. Not Quoting $@
|
|
352
|
+
|
|
353
|
+
### Problem
|
|
354
|
+
```bash
|
|
355
|
+
# Wrong
|
|
356
|
+
script.sh "$@" # Right
|
|
357
|
+
command $@ # Wrong if args have spaces
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Solution
|
|
361
|
+
```bash
|
|
362
|
+
# Right
|
|
363
|
+
command "$@" # Preserves argument boundaries
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## 16. Using ls to Process Files
|
|
369
|
+
|
|
370
|
+
### Problem
|
|
371
|
+
```bash
|
|
372
|
+
# Wrong
|
|
373
|
+
files=$(ls *.txt)
|
|
374
|
+
for file in $files; do
|
|
375
|
+
process "$file"
|
|
376
|
+
done
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Issues
|
|
380
|
+
- Breaks on spaces
|
|
381
|
+
- Breaks on newlines in filenames
|
|
382
|
+
- Breaks on glob characters
|
|
383
|
+
|
|
384
|
+
### Solution
|
|
385
|
+
```bash
|
|
386
|
+
# Right
|
|
387
|
+
for file in *.txt; do
|
|
388
|
+
process "$file"
|
|
389
|
+
done
|
|
390
|
+
|
|
391
|
+
# Or with find
|
|
392
|
+
find . -name "*.txt" -exec process {} \;
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## 17. Incorrect Exit Codes
|
|
398
|
+
|
|
399
|
+
### Problem
|
|
400
|
+
```bash
|
|
401
|
+
# Wrong
|
|
402
|
+
function check_file() {
|
|
403
|
+
if [ -f "$1" ]; then
|
|
404
|
+
echo "File exists"
|
|
405
|
+
return 1 # Success should be 0!
|
|
406
|
+
fi
|
|
407
|
+
return 0
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Solution
|
|
412
|
+
```bash
|
|
413
|
+
# Right - 0 is success, non-zero is failure
|
|
414
|
+
function check_file() {
|
|
415
|
+
if [ -f "$1" ]; then
|
|
416
|
+
echo "File exists"
|
|
417
|
+
return 0
|
|
418
|
+
fi
|
|
419
|
+
return 1
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## 18. Using -a and -o in [ ]
|
|
426
|
+
|
|
427
|
+
### Problem
|
|
428
|
+
```bash
|
|
429
|
+
# Deprecated and error-prone
|
|
430
|
+
[ "$a" = "x" -a "$b" = "y" ]
|
|
431
|
+
[ "$a" = "x" -o "$b" = "y" ]
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### Solution
|
|
435
|
+
```bash
|
|
436
|
+
# Right - use && and ||
|
|
437
|
+
[ "$a" = "x" ] && [ "$b" = "y" ]
|
|
438
|
+
[ "$a" = "x" ] || [ "$b" = "y" ]
|
|
439
|
+
|
|
440
|
+
# Or use [[ ]] in bash
|
|
441
|
+
[[ "$a" = "x" && "$b" = "y" ]]
|
|
442
|
+
[[ "$a" = "x" || "$b" = "y" ]]
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## 19. Not Making Scripts Executable
|
|
448
|
+
|
|
449
|
+
### Problem
|
|
450
|
+
```bash
|
|
451
|
+
# Wrong
|
|
452
|
+
bash script.sh # Works but not ideal
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Solution
|
|
456
|
+
```bash
|
|
457
|
+
# Right
|
|
458
|
+
chmod +x script.sh
|
|
459
|
+
./script.sh
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
And include proper shebang:
|
|
463
|
+
```bash
|
|
464
|
+
#!/usr/bin/env bash
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## 20. Forgetting Final Newline
|
|
470
|
+
|
|
471
|
+
### Problem
|
|
472
|
+
Some tools expect files to end with a newline.
|
|
473
|
+
|
|
474
|
+
### Solution
|
|
475
|
+
Ensure your editor adds a final newline, or:
|
|
476
|
+
```bash
|
|
477
|
+
echo "" >> file
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
## 21. Using grep -q Without Knowing Implications
|
|
483
|
+
|
|
484
|
+
### Problem
|
|
485
|
+
```bash
|
|
486
|
+
# Potentially inefficient
|
|
487
|
+
if [ "$(grep pattern file)" ]; then
|
|
488
|
+
echo "Found"
|
|
489
|
+
fi
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### Solution
|
|
493
|
+
```bash
|
|
494
|
+
# Better - grep -q exits on first match
|
|
495
|
+
if grep -q pattern file; then
|
|
496
|
+
echo "Found"
|
|
497
|
+
fi
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
---
|
|
501
|
+
|
|
502
|
+
## 22. Incorrect glob Pattern
|
|
503
|
+
|
|
504
|
+
### Problem
|
|
505
|
+
```bash
|
|
506
|
+
# Wrong - doesn't match hidden files
|
|
507
|
+
for file in *; do
|
|
508
|
+
process "$file"
|
|
509
|
+
done
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### Solution
|
|
513
|
+
```bash
|
|
514
|
+
# Include hidden files (bash)
|
|
515
|
+
shopt -s dotglob
|
|
516
|
+
for file in *; do
|
|
517
|
+
process "$file"
|
|
518
|
+
done
|
|
519
|
+
shopt -u dotglob
|
|
520
|
+
|
|
521
|
+
# Or explicitly
|
|
522
|
+
for file in * .[!.]* ..?*; do
|
|
523
|
+
[ -e "$file" ] && process "$file"
|
|
524
|
+
done
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
---
|
|
528
|
+
|
|
529
|
+
## 23. Not Handling Empty Globs
|
|
530
|
+
|
|
531
|
+
### Problem
|
|
532
|
+
```bash
|
|
533
|
+
# Fails if no .txt files
|
|
534
|
+
for file in *.txt; do
|
|
535
|
+
process "$file" # Processes literal "*.txt"
|
|
536
|
+
done
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### Solution
|
|
540
|
+
```bash
|
|
541
|
+
# Bash - fail gracefully
|
|
542
|
+
shopt -s nullglob
|
|
543
|
+
for file in *.txt; do
|
|
544
|
+
process "$file"
|
|
545
|
+
done
|
|
546
|
+
shopt -u nullglob
|
|
547
|
+
|
|
548
|
+
# POSIX - check existence
|
|
549
|
+
for file in *.txt; do
|
|
550
|
+
[ -e "$file" ] || continue
|
|
551
|
+
process "$file"
|
|
552
|
+
done
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
## 24. Not Sanitizing Input
|
|
558
|
+
|
|
559
|
+
### Problem
|
|
560
|
+
```bash
|
|
561
|
+
# Dangerous
|
|
562
|
+
rm -rf "/$1" # What if $1 is empty or manipulated?
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### Solution
|
|
566
|
+
```bash
|
|
567
|
+
# Safer
|
|
568
|
+
if [ -z "$1" ]; then
|
|
569
|
+
echo "Error: No argument provided" >&2
|
|
570
|
+
exit 1
|
|
571
|
+
fi
|
|
572
|
+
|
|
573
|
+
# Validate
|
|
574
|
+
case "$1" in
|
|
575
|
+
/*)
|
|
576
|
+
echo "Error: Absolute paths not allowed" >&2
|
|
577
|
+
exit 1
|
|
578
|
+
;;
|
|
579
|
+
esac
|
|
580
|
+
|
|
581
|
+
rm -rf "$1"
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
---
|
|
585
|
+
|
|
586
|
+
## 25. Using -e for File Existence
|
|
587
|
+
|
|
588
|
+
Not a mistake, but be specific:
|
|
589
|
+
|
|
590
|
+
```bash
|
|
591
|
+
[ -e "$file" ] # Exists (any type)
|
|
592
|
+
[ -f "$file" ] # Regular file
|
|
593
|
+
[ -d "$file" ] # Directory
|
|
594
|
+
[ -L "$file" ] # Symbolic link
|
|
595
|
+
[ -r "$file" ] # Readable
|
|
596
|
+
[ -w "$file" ] # Writable
|
|
597
|
+
[ -x "$file" ] # Executable
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
---
|
|
601
|
+
|
|
602
|
+
## Quick Checklist
|
|
603
|
+
|
|
604
|
+
Before running a script, verify:
|
|
605
|
+
|
|
606
|
+
- [ ] Proper shebang (#!/bin/bash or #!/bin/sh)
|
|
607
|
+
- [ ] set -euo pipefail (strict mode)
|
|
608
|
+
- [ ] All variables quoted
|
|
609
|
+
- [ ] Error handling for critical commands
|
|
610
|
+
- [ ] Using $() not backticks
|
|
611
|
+
- [ ] Not using ls for file processing
|
|
612
|
+
- [ ] Functions defined before use
|
|
613
|
+
- [ ] Proper exit codes (0 = success)
|
|
614
|
+
- [ ] Input validation
|
|
615
|
+
- [ ] ShellCheck passes
|
|
616
|
+
|
|
617
|
+
---
|
|
618
|
+
|
|
619
|
+
## Resources
|
|
620
|
+
|
|
621
|
+
- [ShellCheck](https://www.shellcheck.net/) - Catches most of these
|
|
622
|
+
- [Bash Pitfalls](https://mywiki.wooledge.org/BashPitfalls)
|
|
623
|
+
- [POSIX Shell](https://pubs.opengroup.org/onlinepubs/9699919799/)
|