A shell variable holds a string, but an unquoted expansion can turn that string into several command arguments. In Bash, word splitting examines expansion results using IFS as the delimiter set. This is why a pathname that works when typed with quotes can fail after being stored in a variable. Debug the arguments the receiving command actually gets, including empty ones, before blaming the filesystem.
Splitting depends on the context
With the default IFS, runs of spaces, tabs, and newlines separate fields. Leading and trailing IFS whitespace is discarded. An unquoted value containing two words therefore becomes two arguments; an empty unquoted value normally contributes none. In contrast, "$value" supplies one argument even when the string is empty. Empty and absent arguments can have completely different meanings to a program.
Splitting applies to results of unquoted parameter expansion, command substitution, and arithmetic expansion in suitable contexts. It is not a second parse of the entire command line. An ordinary assignment such as copy=$value stores the string without splitting or filename expansion. Later passing $copy unquoted to a command reintroduces both hazards. Bash conditional expressions using double brackets also have different expansion rules from ordinary command arguments.
IFS is a set of delimiter characters, not a multi-character separator or a regular expression. Non-whitespace delimiters behave differently from IFS whitespace: adjacent colons, for example, can produce an empty field. Setting IFS to an empty string disables splitting, but it does not turn an empty unquoted expansion into an explicit empty argument. Use a parser suited to the format when quoting, escaping, or structured records matter.
When it breaks
Disabling splitting does not disable the filename expansion that follows it. A variable containing a star can still become matching filenames when IFS is empty. The result can change merely because a file appeared in the working directory. Quoting the variable prevents both transformations; changing IFS alone only addresses one stage. Shell options controlling globbing are independent as well.
A scalar string is also a poor representation of an argument list. Adding quote characters inside the string does not make Bash treat those characters as shell quotation on expansion. The quotation that controls parsing must be in the command’s source. Avoid eval as a repair: it introduces another shell parse and can execute text that was previously data. For Bash commands assembled incrementally, use an array and expand it as "${args[@]}".
Some data is deliberately delimited, so splitting is not always a mistake. Make the format and delimiter explicit, keep changes to IFS local to the operation, and decide what empty fields mean. Do not use whitespace splitting to process arbitrary filenames or CSV records. These examples specifically target Bash; other shells, including zsh in its normal configuration, do not necessarily split scalar expansions the same way.
For example, a semicolon obtained from a variable does not by itself become a command separator during ordinary expansion. It remains argument data, even though splitting can still damage the surrounding value. This distinction separates incorrect argument construction from deliberately reparsing a string as code.
Check it quickly
This self-contained Bash experiment checks argument counts rather than using echo, which hides the distinction between one spaced argument and several arguments. It creates its own two matching files, tests an empty value, and checks the difference between whitespace and colon delimiters. The temporary directory is removed at exit.
bash --noprofile --norc <<'BASH'
set -e
set +f
unset GLOBIGNORE
shopt -u nullglob failglob dotglob
work=$(mktemp -d)
trap 'rm -rf -- "$work"' EXIT
cd "$work"
IFS=$' \t\n'
value='report final.md'
set -- $value
[[ $# -eq 2 ]]
set -- "$value"
[[ $# -eq 1 && $1 == 'report final.md' ]]
value=''
set -- $value
[[ $# -eq 0 ]]
set -- "$value"
[[ $# -eq 1 && $1 == '' ]]
touch a.txt 'two words.txt'
IFS=''
pattern='*.txt'
set -- $pattern
[[ $# -eq 2 ]]
set -- "$pattern"
[[ $# -eq 1 && $1 == '*.txt' ]]
IFS=:
record='red::blue'
set -- $record
[[ $# -eq 3 && $2 == '' ]]
printf 'colon field <%s>\n' "$@"
args=('report final.md' '' '*.txt')
set -- "${args[@]}"
[[ $# -eq 3 && $2 == '' && $3 == '*.txt' ]]
printf 'PASS: boundaries, empty values, globbing, delimiters\n'
BASH
Expect three colon-field lines, with an empty middle field, followed by PASS. The assertions before those lines distinguish zero arguments from one empty argument and prove that an empty IFS still permits globbing. In a failing script, put a small argument-counting function at the call boundary and print each argument separately with Bash printf’s %q format. That diagnostic shows boundaries and escaping; it does not turn a human-readable log into a safe command to execute later.
Sources
- GNU Bash: Word Splitting, IFS and empty-field rules, checked 2026-09-06.
- GNU Bash: Shell Expansions, splitting before filename expansion, checked 2026-09-06.
- GNU Bash: Arrays, preserving a list of arguments, checked 2026-09-06.