@hybridlabor-api/aos 4.8.0 → 4.9.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 +1 -1
- package/.agents/nodes.json +1 -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/settings.json +13 -0
- package/.opencode/agents/godmode-media-eventtech.md +1 -1
- package/.opencode/plugins/bdb-aos.js +31 -4
- package/README.de.md +1 -1
- package/README.md +1 -1
- package/README.pt.md +1 -1
- package/THIRD_PARTY_NOTICES.md +88 -0
- package/docs/skills_table.md +1 -1
- package/installer.js +174 -46
- package/package.json +6 -2
- 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/global_config/agenttrail/SKILL.md +6 -1
- package/skills/global_config/ask-tim/SKILL.md +4 -4
- 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/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/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 +139 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
# POSIX Shell (sh) Reference Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
POSIX sh is the portable shell specification defined by POSIX standards. Scripts written for POSIX sh should work across different Unix-like systems (bash, dash, ksh, etc.).
|
|
6
|
+
|
|
7
|
+
**Official Specification:** https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
|
|
8
|
+
|
|
9
|
+
## Why POSIX Shell Matters
|
|
10
|
+
|
|
11
|
+
- **Portability**: Works across different Unix systems and shells
|
|
12
|
+
- **Minimal dependencies**: Available in minimal environments (containers, embedded systems)
|
|
13
|
+
- **Faster**: Shells like dash are faster than bash for simple scripts
|
|
14
|
+
- **Compatibility**: /bin/sh may not be bash (Ubuntu/Debian use dash)
|
|
15
|
+
|
|
16
|
+
## Key Differences: sh vs bash
|
|
17
|
+
|
|
18
|
+
### Features NOT Available in POSIX sh
|
|
19
|
+
|
|
20
|
+
1. **Arrays**
|
|
21
|
+
```bash
|
|
22
|
+
# Bash only - NOT POSIX
|
|
23
|
+
array=(one two three)
|
|
24
|
+
echo "${array[0]}"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
2. **[[ ]] Test Construct**
|
|
28
|
+
```bash
|
|
29
|
+
# Bash only - NOT POSIX
|
|
30
|
+
if [[ "$var" == "value" ]]; then
|
|
31
|
+
|
|
32
|
+
# POSIX sh - use [ ]
|
|
33
|
+
if [ "$var" = "value" ]; then
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
3. **== Operator**
|
|
37
|
+
```bash
|
|
38
|
+
# Bash style - NOT POSIX
|
|
39
|
+
[ "$a" == "$b" ]
|
|
40
|
+
|
|
41
|
+
# POSIX sh - use single =
|
|
42
|
+
[ "$a" = "$b" ]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
4. **Process Substitution**
|
|
46
|
+
```bash
|
|
47
|
+
# Bash only - NOT POSIX
|
|
48
|
+
diff <(ls dir1) <(ls dir2)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
5. **Brace Expansion**
|
|
52
|
+
```bash
|
|
53
|
+
# Bash only - NOT POSIX
|
|
54
|
+
echo {1..10}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
6. **function Keyword**
|
|
58
|
+
```bash
|
|
59
|
+
# Bash style - NOT in original POSIX
|
|
60
|
+
function myfunc {
|
|
61
|
+
echo "hello"
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# POSIX sh style
|
|
65
|
+
myfunc() {
|
|
66
|
+
echo "hello"
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
7. **local Keyword**
|
|
71
|
+
```bash
|
|
72
|
+
# Common but not in POSIX standard
|
|
73
|
+
local var="value"
|
|
74
|
+
|
|
75
|
+
# POSIX alternative: use function scope carefully
|
|
76
|
+
# or use naming conventions
|
|
77
|
+
_func_var="value"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
8. **source Command**
|
|
81
|
+
```bash
|
|
82
|
+
# Bash style - NOT POSIX
|
|
83
|
+
source script.sh
|
|
84
|
+
|
|
85
|
+
# POSIX sh
|
|
86
|
+
. script.sh
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## POSIX Shell Syntax
|
|
90
|
+
|
|
91
|
+
### Variables
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
# Assignment
|
|
95
|
+
var="value"
|
|
96
|
+
readonly CONST="constant"
|
|
97
|
+
|
|
98
|
+
# Reading variables
|
|
99
|
+
echo "$var"
|
|
100
|
+
echo "${var}"
|
|
101
|
+
|
|
102
|
+
# Command substitution (POSIX)
|
|
103
|
+
result=$(command)
|
|
104
|
+
|
|
105
|
+
# Old-style command substitution (works but deprecated)
|
|
106
|
+
result=`command`
|
|
107
|
+
|
|
108
|
+
# Arithmetic (POSIX way)
|
|
109
|
+
result=$((5 + 3))
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Quoting
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
# Double quotes: Preserve literal value except $, `, and \
|
|
116
|
+
echo "Value: $var"
|
|
117
|
+
|
|
118
|
+
# Single quotes: Preserve everything literally
|
|
119
|
+
echo 'Value: $var'
|
|
120
|
+
|
|
121
|
+
# Always quote variables
|
|
122
|
+
cp "$file" "$destination"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Control Structures
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
# If statement
|
|
129
|
+
if [ condition ]; then
|
|
130
|
+
# commands
|
|
131
|
+
elif [ condition ]; then
|
|
132
|
+
# commands
|
|
133
|
+
else
|
|
134
|
+
# commands
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
# Case statement
|
|
138
|
+
case "$var" in
|
|
139
|
+
pattern1)
|
|
140
|
+
# commands
|
|
141
|
+
;;
|
|
142
|
+
pattern2|pattern3)
|
|
143
|
+
# commands
|
|
144
|
+
;;
|
|
145
|
+
*)
|
|
146
|
+
# default
|
|
147
|
+
;;
|
|
148
|
+
esac
|
|
149
|
+
|
|
150
|
+
# For loop
|
|
151
|
+
for item in list; do
|
|
152
|
+
echo "$item"
|
|
153
|
+
done
|
|
154
|
+
|
|
155
|
+
# While loop
|
|
156
|
+
while [ condition ]; do
|
|
157
|
+
# commands
|
|
158
|
+
done
|
|
159
|
+
|
|
160
|
+
# Until loop
|
|
161
|
+
until [ condition ]; do
|
|
162
|
+
# commands
|
|
163
|
+
done
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Test Constructs
|
|
167
|
+
|
|
168
|
+
POSIX sh uses `[ ]` (also known as `test` command):
|
|
169
|
+
|
|
170
|
+
```sh
|
|
171
|
+
# String comparisons
|
|
172
|
+
[ "$a" = "$b" ] # Equal
|
|
173
|
+
[ "$a" != "$b" ] # Not equal
|
|
174
|
+
[ -z "$a" ] # String is empty
|
|
175
|
+
[ -n "$a" ] # String is not empty
|
|
176
|
+
|
|
177
|
+
# Numeric comparisons
|
|
178
|
+
[ "$a" -eq "$b" ] # Equal
|
|
179
|
+
[ "$a" -ne "$b" ] # Not equal
|
|
180
|
+
[ "$a" -lt "$b" ] # Less than
|
|
181
|
+
[ "$a" -le "$b" ] # Less than or equal
|
|
182
|
+
[ "$a" -gt "$b" ] # Greater than
|
|
183
|
+
[ "$a" -ge "$b" ] # Greater than or equal
|
|
184
|
+
|
|
185
|
+
# File tests
|
|
186
|
+
[ -e "$file" ] # File exists
|
|
187
|
+
[ -f "$file" ] # Regular file exists
|
|
188
|
+
[ -d "$file" ] # Directory exists
|
|
189
|
+
[ -r "$file" ] # File is readable
|
|
190
|
+
[ -w "$file" ] # File is writable
|
|
191
|
+
[ -x "$file" ] # File is executable
|
|
192
|
+
[ -s "$file" ] # File is not empty
|
|
193
|
+
|
|
194
|
+
# Logical operators
|
|
195
|
+
[ condition1 ] && [ condition2 ] # AND
|
|
196
|
+
[ condition1 ] || [ condition2 ] # OR
|
|
197
|
+
[ ! condition ] # NOT
|
|
198
|
+
[ condition1 -a condition2 ] # AND (inside test)
|
|
199
|
+
[ condition1 -o condition2 ] # OR (inside test)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Functions
|
|
203
|
+
|
|
204
|
+
```sh
|
|
205
|
+
# POSIX function definition
|
|
206
|
+
function_name() {
|
|
207
|
+
# No 'local' in strict POSIX
|
|
208
|
+
# Use careful scoping or naming conventions
|
|
209
|
+
echo "$1" # First argument
|
|
210
|
+
return 0 # Exit status
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
# Call function
|
|
214
|
+
function_name arg1 arg2
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Input/Output Redirection
|
|
218
|
+
|
|
219
|
+
```sh
|
|
220
|
+
# Redirect stdout
|
|
221
|
+
command > file
|
|
222
|
+
|
|
223
|
+
# Redirect stderr
|
|
224
|
+
command 2> errors.txt
|
|
225
|
+
|
|
226
|
+
# Redirect both
|
|
227
|
+
command > output.txt 2>&1
|
|
228
|
+
|
|
229
|
+
# Append
|
|
230
|
+
command >> file
|
|
231
|
+
|
|
232
|
+
# Here document
|
|
233
|
+
cat <<EOF
|
|
234
|
+
multiple
|
|
235
|
+
lines
|
|
236
|
+
of text
|
|
237
|
+
EOF
|
|
238
|
+
|
|
239
|
+
# Read from stdin
|
|
240
|
+
while read -r line; do
|
|
241
|
+
echo "$line"
|
|
242
|
+
done < file.txt
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## POSIX Best Practices
|
|
246
|
+
|
|
247
|
+
### 1. Proper Shebang
|
|
248
|
+
```sh
|
|
249
|
+
#!/bin/sh
|
|
250
|
+
# Use /bin/sh for POSIX scripts, not /bin/bash
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### 2. Quote All Variables
|
|
254
|
+
```sh
|
|
255
|
+
# Good
|
|
256
|
+
cp "$source" "$destination"
|
|
257
|
+
|
|
258
|
+
# Bad
|
|
259
|
+
cp $source $destination
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### 3. Use = Not ==
|
|
263
|
+
```sh
|
|
264
|
+
# POSIX compliant
|
|
265
|
+
if [ "$var" = "value" ]; then
|
|
266
|
+
|
|
267
|
+
# NOT POSIX (bash-specific)
|
|
268
|
+
if [ "$var" == "value" ]; then
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### 4. Use $() for Command Substitution
|
|
272
|
+
```sh
|
|
273
|
+
# Preferred (POSIX)
|
|
274
|
+
result=$(command)
|
|
275
|
+
|
|
276
|
+
# Old style (works but less readable)
|
|
277
|
+
result=`command`
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### 5. Avoid Bashisms
|
|
281
|
+
|
|
282
|
+
Don't use:
|
|
283
|
+
- Arrays: `array=(one two)`
|
|
284
|
+
- `[[` test construct
|
|
285
|
+
- Process substitution: `<(command)`
|
|
286
|
+
- Brace expansion: `{1..10}`
|
|
287
|
+
- `function` keyword
|
|
288
|
+
- `source` command (use `.` instead)
|
|
289
|
+
- `==` operator (use `=`)
|
|
290
|
+
- `$RANDOM` variable
|
|
291
|
+
|
|
292
|
+
### 6. Check Command Existence
|
|
293
|
+
```sh
|
|
294
|
+
if command -v shellcheck >/dev/null 2>&1; then
|
|
295
|
+
echo "ShellCheck is installed"
|
|
296
|
+
fi
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### 7. Handle Errors
|
|
300
|
+
```sh
|
|
301
|
+
# Set errexit
|
|
302
|
+
set -e
|
|
303
|
+
|
|
304
|
+
# Or check manually
|
|
305
|
+
if ! command; then
|
|
306
|
+
echo "Command failed" >&2
|
|
307
|
+
exit 1
|
|
308
|
+
fi
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### 8. Use set -u for Undefined Variables
|
|
312
|
+
```sh
|
|
313
|
+
set -u
|
|
314
|
+
# Now accessing undefined variables causes error
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Common Portability Issues
|
|
318
|
+
|
|
319
|
+
### 1. echo Command
|
|
320
|
+
```sh
|
|
321
|
+
# Portable way to echo without newline
|
|
322
|
+
printf '%s' "text without newline"
|
|
323
|
+
|
|
324
|
+
# echo -n is not portable
|
|
325
|
+
echo -n "text" # Don't use in POSIX sh
|
|
326
|
+
|
|
327
|
+
# echo with backslashes
|
|
328
|
+
printf '%s\n' "text\twith\ttabs"
|
|
329
|
+
echo "text\twith\ttabs" # Behavior varies
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### 2. Array Alternatives
|
|
333
|
+
```sh
|
|
334
|
+
# Instead of arrays, use:
|
|
335
|
+
|
|
336
|
+
# 1. Positional parameters
|
|
337
|
+
set -- one two three
|
|
338
|
+
echo "$1" # one
|
|
339
|
+
|
|
340
|
+
# 2. Delimited strings
|
|
341
|
+
items="one:two:three"
|
|
342
|
+
IFS=:
|
|
343
|
+
for item in $items; do
|
|
344
|
+
echo "$item"
|
|
345
|
+
done
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### 3. String Manipulation
|
|
349
|
+
```sh
|
|
350
|
+
# POSIX parameter expansion
|
|
351
|
+
${var#pattern} # Remove shortest match from beginning
|
|
352
|
+
${var##pattern} # Remove longest match from beginning
|
|
353
|
+
${var%pattern} # Remove shortest match from end
|
|
354
|
+
${var%%pattern} # Remove longest match from end
|
|
355
|
+
|
|
356
|
+
# NOT POSIX (bash-specific)
|
|
357
|
+
${var/pattern/replacement}
|
|
358
|
+
${var,,} # lowercase
|
|
359
|
+
${var^^} # uppercase
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### 4. Arithmetic
|
|
363
|
+
```sh
|
|
364
|
+
# POSIX way
|
|
365
|
+
result=$((a + b))
|
|
366
|
+
|
|
367
|
+
# NOT POSIX (bash-specific)
|
|
368
|
+
((a++))
|
|
369
|
+
let "a = a + 1"
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### 5. read Command
|
|
373
|
+
```sh
|
|
374
|
+
# POSIX
|
|
375
|
+
while IFS= read -r line; do
|
|
376
|
+
echo "$line"
|
|
377
|
+
done < file
|
|
378
|
+
|
|
379
|
+
# Bash-specific flags to avoid:
|
|
380
|
+
read -p "prompt" # Not in POSIX
|
|
381
|
+
read -a array # Not in POSIX
|
|
382
|
+
read -t timeout # Not in POSIX
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## POSIX Parameter Expansion
|
|
386
|
+
|
|
387
|
+
```sh
|
|
388
|
+
${var} # Value of var
|
|
389
|
+
${var:-default} # Use default if var is unset or null
|
|
390
|
+
${var:=default} # Assign default if var is unset or null
|
|
391
|
+
${var:?error} # Error if var is unset or null
|
|
392
|
+
${var:+alternate} # Use alternate if var is set and not null
|
|
393
|
+
${#var} # Length of var
|
|
394
|
+
${var#pattern} # Remove shortest match from beginning
|
|
395
|
+
${var##pattern} # Remove longest match from beginning
|
|
396
|
+
${var%pattern} # Remove shortest match from end
|
|
397
|
+
${var%%pattern} # Remove longest match from end
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
## Special Variables (POSIX)
|
|
401
|
+
|
|
402
|
+
```sh
|
|
403
|
+
$0 # Script name
|
|
404
|
+
$1-$9 # Positional parameters
|
|
405
|
+
${10} # Parameters beyond 9 (braces required)
|
|
406
|
+
$# # Number of positional parameters
|
|
407
|
+
$* # All positional parameters (as single word)
|
|
408
|
+
$@ # All positional parameters (as separate words)
|
|
409
|
+
$$ # Process ID of shell
|
|
410
|
+
$! # PID of last background command
|
|
411
|
+
$? # Exit status of last command
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## Testing for POSIX Compliance
|
|
415
|
+
|
|
416
|
+
### Use checkbashisms
|
|
417
|
+
```sh
|
|
418
|
+
# Install checkbashisms (Debian/Ubuntu)
|
|
419
|
+
apt-get install devscripts
|
|
420
|
+
|
|
421
|
+
# Check script
|
|
422
|
+
checkbashisms script.sh
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Use ShellCheck with sh
|
|
426
|
+
```sh
|
|
427
|
+
# Validate as sh script
|
|
428
|
+
shellcheck -s sh script.sh
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### Test with Different Shells
|
|
432
|
+
```sh
|
|
433
|
+
# Test with dash (common /bin/sh)
|
|
434
|
+
dash script.sh
|
|
435
|
+
|
|
436
|
+
# Test with ash
|
|
437
|
+
ash script.sh
|
|
438
|
+
|
|
439
|
+
# Test with ksh
|
|
440
|
+
ksh script.sh
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## Common POSIX Utilities
|
|
444
|
+
|
|
445
|
+
These utilities are standardized and safe to use in POSIX scripts:
|
|
446
|
+
|
|
447
|
+
- `cat`, `echo`, `printf`
|
|
448
|
+
- `grep`, `sed`, `awk`
|
|
449
|
+
- `cut`, `sort`, `uniq`, `tr`
|
|
450
|
+
- `head`, `tail`, `wc`
|
|
451
|
+
- `find`, `xargs`
|
|
452
|
+
- `test` (same as `[ ]`)
|
|
453
|
+
- `cd`, `pwd`, `ls`
|
|
454
|
+
- `cp`, `mv`, `rm`, `mkdir`
|
|
455
|
+
- `chmod`, `chown`
|
|
456
|
+
- `read`, `shift`, `set`, `export`
|
|
457
|
+
|
|
458
|
+
## Resources
|
|
459
|
+
|
|
460
|
+
- [POSIX Shell Command Language](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html)
|
|
461
|
+
- [Dash as /bin/sh](https://wiki.ubuntu.com/DashAsBinSh)
|
|
462
|
+
- [Autoconf Portable Shell](https://www.gnu.org/software/autoconf/manual/autoconf.html#Portable-Shell)
|
|
463
|
+
- [Rich's sh (POSIX shell) tricks](http://www.etalabs.net/sh_tricks.html)
|