我有一个 bash 脚本(见此处),用于按文件名对子目录中的文件列表进行排序。
这个脚本在追加排序的文件hooks/pre-relevant/,那么文件命名 hooks/pre-relevant,然后文件命名hooks/relevant,然后排序的文件中hooks/relevant/,使用append_hook以下功能:
hooks=()
# Run a hook script, if it's executable, with the input from this invocation
append_hook () {
if [[ -f "$1" && -x "$1" ]]; then
hooks+=("$1")
fi
}
Run Code Online (Sandbox Code Playgroud)
我正在用这个目录结构测试它:
testing-range/plugins/
|-- bar
| `-- hooks
| |-- irrelevant
| |-- only-one
| `-- relevant
|-- dickory
| `-- hooks
| `-- pre-relevant
|-- doc
| `-- hooks
| |-- perl-envsubst
| `-- relevant
| |-- 00
| `-- 20
|
|-- factory
| `-- hooks
| `-- relevant
`-- hickory
`-- hooks
|-- pre-relevant
| `-- 30
`-- relevant
`-- 10
Run Code Online (Sandbox Code Playgroud)
当我使用这个多步数组代码附加文件时:
append_numbered_hooks () {
# Gather every file into an array, prefixing each item with the
# filename of the script (its position in sort order)
local filelist=()
for hook in "$PLUSHU_ROOT"/plugins/*/hooks/"$hookname"/*; do
filelist+=("${hook##*/}/$hook")
done
# Sort the array numerically
printf '%s\0' "${filelist[@]}" | sort -nz | IFS= read -rd '' -a filelist
# Append each script in sorted order
for hookline in "${filelist[@]}"; do
append_hook "${hookline#*/}"
done
}
Run Code Online (Sandbox Code Playgroud)
我得到几乎正确的输出:
hickory/hooks/pre-relevant/30
dickory/hooks/pre-relevant
bar/hooks/relevant
factory/hooks/relevant
doc/hooks/relevant/00
doc/hooks/relevant/20
hickory/hooks/relevant/10
Run Code Online (Sandbox Code Playgroud)
然而,当我使用这个更简单的管道附加文件时:
append_numbered_hooks () {
for hook in "$PLUSHU_ROOT"/plugins/*/hooks/"$1"/*; do
printf '%s\0' "${hook##*/}/$hook"
done | sort -nz | while IFS= read -rd '' hookline; do
append_hook "${hookline#*/}"
done
}
Run Code Online (Sandbox Code Playgroud)
编号文件不会出现在 for "${hooks[@]}" 循环中:
dickory/hooks/pre-relevant
bar/hooks/relevant
factory/hooks/relevant
Run Code Online (Sandbox Code Playgroud)
这是怎么回事?正确的值应该是:
hickory/hooks/pre-relevant/30
dickory/hooks/pre-relevant
bar/hooks/relevant
factory/hooks/relevant
doc/hooks/relevant/00
hickory/hooks/relevant/10
doc/hooks/relevant/20
Run Code Online (Sandbox Code Playgroud)
来自http://www.gnu.org/software/bash/manual/bashref.html#Pipelines
管道中的每个命令都在其自己的子 shell 中执行
因此,您正在更改子shell 中的变量。当 subshell 退出时,这些更改就会消失。
您可能会发现过程替换很有帮助。
append_numbered_hooks () {
while IFS= read -rd '' hookline; do
append_hook "${hookline#*/}"
done < <(
for hook in "$PLUSHU_ROOT"/plugins/*/hooks/"$1"/*; do
printf '%s\0' "${hook##*/}/$hook"
done |
sort -nz
)
}
Run Code Online (Sandbox Code Playgroud)