Bash技术问询:使用循环将find命令结果追加至索引数组失败及数组+=运算符疑问
Let's break down your two issues one by one, since they're related but have distinct fixes:
1. Why your manual array test didn't work
Your pids+="foo1" syntax is incorrect for adding elements to a Bash array. When you use += without parentheses, you're appending the string directly to the first element of the array, not adding a new element. That's why you ended up with pids[0]="foo1foo2" instead of two separate elements.
The correct way to add elements to an array is to wrap the value in parentheses:
declare -a pids pids+=("foo1") # Adds "foo1" as pids[0] pids+=("foo2") # Adds "foo2" as pids[1]
2. Why your find/while loop didn't populate the array
The bigger issue here is subshell behavior in Bash. When you pipe output from find to a while loop (find ... | while read ...), the while loop runs in a separate subshell. Any changes you make to the pids array inside this subshell won't be reflected in the parent shell where you later try to iterate over it. That's why your final for loop has nothing to output.
Here are three reliable fixes for this:
Fix 1: Use process substitution (most portable for modern Bash)
Replace the pipe with process substitution to run the while loop in your current shell instead of a subshell:
declare -a pids while read -d $'\0' file do pids+=("$file") done < <(find /foo/bar/ -iname "*.pid" -print0) # Now pids is populated in the parent shell for i in "${pids[@]}" do echo "$i" done
The < <(command) syntax feeds the output of find directly into the while loop's standard input, keeping the loop in the main shell context.
Fix 2: Group all logic in the same subshell (if you don't need the array later)
If you only need to process the files immediately and don't need the pids array outside the loop, wrap the entire array setup and iteration in a subshell group:
find /foo/bar/ -iname "*.pid" -print0 | { declare -a pids while read -d $'\0' file do pids+=("$file") done for i in "${pids[@]}" do echo "$i" done }
This works because all operations happen in the same subshell, so the array is accessible to the for loop inside the group.
Fix 3: Enable lastpipe (Bash 4.2+)
If you're using Bash 4.2 or newer, you can enable the lastpipe option to make the last command in a pipe run in the current shell:
shopt -s lastpipe declare -a pids find /foo/bar/ -iname "*.pid" -print0 | while read -d $'\0' file do pids+=("$file") done for i in "${pids[@]}" do echo "$i" done
This preserves your original pipe structure but modifies how Bash handles the last command in the pipeline.
Quick Recap
- Always use
array+=("value")to add new elements to a Bash array (parentheses are mandatory). - Pipe-induced subshells are the root cause of your empty array; use process substitution,
lastpipe, or subshell grouping to fix it.
内容的提问来源于stack exchange,提问作者Icoryx

