0

I know that the following is bad:

for i in `ls -1 *.MOV` ;do ...

and that the proper syntax is

for i in  *.MOV ;do ...

But what are the mechanics behind it? I mean, what part of *.MOV tells the for command that I'm talking about filenames? Is there an assumption made in the for code that says "given no other parameters, assume filenames"?

And... if ls output is bad inside of for, what is for doing to get a usable list of filenames that it wont choke on?

3

1 Answer 1

2

Yes :-) The shell is expanding the wildcard to the set of files matching the wild-card expression, in your example the MOV files in the current directory. But six other kinds of expansion must be considered before this happens.

'Expansion' is described in a detailed way in the manual man bash.

EXPANSION

Expansion is performed on the command line after it has been split into words. There are seven kinds of expansion performed: brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, word splitting, and pathname expansion.

...

Pathname Expansion

After word splitting, unless the -f option has been set, bash scans each word for the characters *, ?, and [. If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of filenames matching the pattern (see Pattern Matching below). If no matching filenames are found, and the shell option nullglob is not enabled, the word is left unchanged.

3
  • 1
    This is very helpful for the first part of my question. Excellent, thank you! Now for the second part -- how is "for" or the "shell expansion" putting the list of filenames in $i in a way that doesn't break everything following that would depend on $i ? Is it that there is no interpretation of the filename content with the pathname expansion, but that ls tries to interpret special characters in some way that botches it? I'm just trying to understand the underlying mechanism where in one case $i can be trusted to be accurate and in the other way it can't.
    – mikem
    Commented Jul 30, 2022 at 21:09
  • 2
    The glob *.MOV is replaced by the set of matching files. Thereafter the loop can be considered to iterate across a set of literals: for f in first.MOV second.MOV third.MOV Commented Jul 30, 2022 at 22:01
  • 2
    @mikem: ls itself doesn't do anything bad, but (per the man page) command substitution with backticks or $( ... ) is normally followed by word splitting and (another) pathname expansion, which can damage your values. These can be suppressed by set -f and changing IFS (unless your filenames ever contain newline because that becomes ambiguous, plus any trailing newlines are removed), but doing that tends to break other things. And for i in *x sets i correctly but remember you still must doublequote its expansion "$i" or that may mangle. Commented Jul 31, 2022 at 1:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .