1

Where this script is located, I have multiple sub-directories in which I would like to run a single command on all of the contents. The contents are also numbered in ascending order. Using for f in * in folders with 10+ items results in files named 10 or 11 coming sequentially before 1..9.

Additionally, The number of files in each sub-directory varies between 6 and 12 items so I don't think I can simply do a range operation like {1..12} because I would like to avoid warnings/errors about nonexistent files.

Question: Is there a way to force or modify the for loop to maintain ascending numerical order when iterating over the entire contents of a folder without knowing the quantity of the folders contents?

term=""                  # hold accumulated filenames

for d in */ ; do         # iterate over sub-directories
    cd $d
    for f in * ; do      # iterate over files in sub-directory
        term="$term $f"
    done
    # run a command using the string $term
    term=""
    cd ..
done

Side note: I tagged sh, shell and bash since they are all applicable to this problem. I read Difference between sh and bash before adding both tags to ensure it would be a valid choice even though there are some syntax/portability variations and such.

Community
  • 1
  • 1
Darrel Holt
  • 870
  • 1
  • 15
  • 39

1 Answers1

1

You can use the ls option -v for this. From man ls:

-v natural sort of (version) numbers within text

If you change your inner loop to

for f in `ls -v` ; do      # iterate over files in sub-directory
    term="$term $f"
done

The results from ls will be sorted ascending numerical order.

Another option is sort, from man sort:

-g, --general-numeric-sort compare according to general numerical value

Piping the results from ls through sort -g gives the same result.

Edit

Since using the output of ls to get filenames is a bad idea, consider also using find instead, e.g.

for f in `find * -type f | sort -g`; do
    ...
resc
  • 541
  • 6
  • 11