Question

I'm relatively new to shell scripting, but not to programming, though I'll admit to being out of the game for a while.

In trying to get the bottom of a bug in a Bash script, I've come up with three short examples of my use of process substitution and "here strings" feeding STDIN for while loops, in order to avoid subshell issues.

I'm null-separating the find output to avoid potential struggles with unusual filename characters.

This example works great, and outputs the names of all folders in root:

#!/bin/bash
while IFS= read -r -d '' y; do echo "${y}"
done < <(find / -type d -maxdepth 1 -mindepth 1 -printf "%P\0" | sort -z)

This example works great, too:

#!/bin/bash
find / -type d -maxdepth 1 -mindepth 1 -printf "%P\0" | sort -z | \
{ while IFS= read -r -d '' y; do echo "${y}"; done }

But this case, where I store the find output in string x and attempt to use it as the source of my "here string", outputs nothing:

#!/bin/bash
x=$(find / -type d -maxdepth 1 -mindepth 1 -printf "%P\0" | sort -z)
while IFS= read -r -d '' y; do echo "${y}"; done <<< "${x}"

What subtlety (or denseness on my part) am I missing here?

I'm using GNU bash 4.1.7(2)-release.

Was it helpful?

Solution

Strings in bash are like C-strings and are null-terminated. This should explain why it doesn't work when you try to assign the output to a variable.

As an experiment, you could try

a=$'foo\0bar'
echo "$a"

OTHER TIPS

When you assign a string to a parameter, the end of the string is terminated by the first null character. The shell can, however, pass null-character-containing strings via standard input, which can read an arbitrary byte stream.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top