I am doing this in OSX which uses bash but obviously, not all bash conventions are used so hopefully your suggestion is available to me :)

I have the following files

  1. fun bar1.txt
  2. Foo bar2.tXT (that's an uppercase XT)
  3. fun fun.txt

What I was is to iterate through the file list in a sorted manner?

something like:

for i in (my-sorted-file-list); do
    echo $i

Any ideas how this can be done? thanks a lot


Very simple:

for i in *; do
  echo "<$i>"

This uses bash's file globbing. A sort is not necessary as bash already sorts pathname expansions.
From man bash:

   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 file
       names matching the pattern.


Example result:

$ touch 'fun bar1.txt' 'Foo bar2.tXT' 'fun fun.txt'

$ for i in *; do echo "<$i>"; done
<Foo bar2.tXT>
<fun bar1.txt>
<fun fun.txt>

Note that the sort order is dependent upon LC_COLLATE (just like the sort utility). If you want a case insensitive sort, use LC_COLLATE=en_US.utf8. If you want a case sensitive sort, use LC_COLLATE=C.

Also man bash:

          This variable determines the collation order used when sorting the results
          of pathname expansion, and determines the behavior of range expressions,
          equivalence classes, and collating sequences within pathname expansion and
          pattern matching.
| improve this answer | |

One thing to bear in mind: in

for i in *.{txt,py,c}; do ...

The *.{txt,py,c} is first expanded to *.txt *.py *.c.

While *.txt is sorted, *.{txt,py,c} is not. It also means that if there's not .py file, you will loop over the literal string *.py.

If you want a sorted global list, you should use an alternation globbing operator instead of brace expansion. With bash:

shopt -s extglob
for i in *.@(txt|py|c); do...

Whether the sorting will be done case sensitively or not is locale specific. To force case insensitive sorting in the current locale, with zsh, you can define a new sorting order like:

ci() REPLY=${(L)REPLY}
for i (*.(txt|py|c))(N.o+ci)) {...}
| improve this answer | |

If none contain newlines, then this will get you a sorted list:

_state=$(set +o)
set -f
' ; for f in $(set +f; printf %s\\n * |sort) ; do echo "$f" ; done
eval "$_state"

That is, it will get you a sorted list of all of the files in the current directory - here represented by *.

| improve this answer | |
  • contain newlines... or globbing characters. – Stéphane Chazelas Jul 23 '14 at 7:02
  • @StéphaneChazelas - thank you - that is a good point. I edited it a little. Thanks twice - I should have thought harder about that edit, huh? – mikeserv Jul 23 '14 at 12:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.