Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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
done

Any ideas how this can be done? thanks a lot

share|improve this question

3 Answers 3

Very simple:

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

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:

   LC_COLLATE
          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.
share|improve this answer

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

_state=$(set +o)
set -f
IFS='
' ; 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 *.

share|improve this answer
    
contain newlines... or globbing characters. –  Stéphane Chazelas Jul 23 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 at 12:28

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)) {...}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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