I have a folder with a lot of shell scripts to configure my server.

My main script is named "setup.sh" and all others scripts are named 0.script.sh, 1.script.sh.... More generally N.SCRIPT_NAME.sh, where N is the execution number.

So, I would like to list all shell scripts from the folder, and execute them in the order specified by the N numbers.

  • A simple for s in *.script.sh; do printf '%s\n' "$s"; done should list the scripts in lexicographical order. Is that the order you need? If that is not what you need, the questions multiply: Are the numbers N only one digit? Do the numbers have leading zero(s)? etc … etc …
    – user232326
    Commented Nov 16, 2018 at 18:52
  • There are no leading zero, and N can have more than one digit.
    – graille
    Commented Nov 16, 2018 at 18:54
  • Read man run-,parts.
    – waltinator
    Commented Nov 16, 2018 at 19:44
  • @don_crissti Based on which reasoning you have decided to remove the OP tag of bash? Could (s)he not choose which shell to use/ask about?
    – user232326
    Commented Nov 16, 2018 at 20:31
  • 2
    @Isaac - based on the fact that almost all newcomers tag their questions linux & bash regardless of the content and there's nothing bash-specific here (and it's already tagged shell). You can always add it back if you think this is a bash question. Commented Nov 16, 2018 at 20:40

2 Answers 2


There's probably an easier way to glob filenames in sequence with zsh, but here's a brute-force way in bash:

for script in ?.script*.sh ??.script*.sh ???.script*.sh ????.script*.sh
  printf "Executing script: %s\n" "$script"

This assumes that you have no more than 9999 scripts -- or, more precisely, none with more than 4 numbers (characters) in the prefix part of the filename.

It also assumes that the prefixes are numbered -- it will pick up scripts named, e.g. go.script_X.sh, if you had one. To work around that, replace the ? with [0-9]'s:

for f in [0-9].script*.sh [0-9][0-9].script*.sh ...

The shell's natural globbing mechanism will be to sort the resulting filenames alphabetically, which results in them sorting numerically as well. The various filenames are spelled out in increasing scale so that "9" sorts before "101" & etc.

In zsh, glob the filenames in numerical order of their prefix with:

for script in *.script*.sh(oe_'REPLY=${REPLY%%.*}'_n)
  printf "Executing script: %s\n" "$script"

The globbing expansion first picks up all of the *.script*.sh files, then says to order (sort) them using the expression that extracts the prefix by stripping as much of "dot followed by anything" as possible, and using a numeric sort.

  • Ideally OP would zero-pad the file names, then using a simple glob like ./* should work with any shell... Commented Nov 16, 2018 at 19:31
  • Thanks for the edit, don; I'm still experimenting with zsh.
    – Jeff Schaller
    Commented Nov 16, 2018 at 19:32
  • No problem. You could also use a function as shown here Commented Nov 16, 2018 at 19:35
  • Ahhh; I had searched here for zsh filename sorting and landed on one of Gilles' answers and ran with it. Credit to Gilles, blame to me!
    – Jeff Schaller
    Commented Nov 16, 2018 at 19:38
  • 1
    Why the complexity in zsh? This zsh -c 'for script in folder/*.script*.sh(n);do printf "Executing script: %s\n" "$script";done' seems to work correctly. Reference
    – user232326
    Commented Nov 16, 2018 at 19:53

If the files names are simple (no spaces, no newlines, no characters that ls needs to encode with a ?) then, maybe !! , you can get away with:

IFS=$' \t\n'; for s in $(ls -v folder/*.script.sh); do printf '%s\n' "$s"; done

In this case, ls will sort by version number -v (quite similar to numeric value).

But in general, it is a bad idea to parse (process) the output of ls.

This is better:

shopt -s nullglob
for   s   in   folder/?{,?{,?{,?}}}.script.sh
do    printf '%s\n' "$s"

Which will list (in alphabetical order, which is equivalent to numerical order if the characters before .script.sh are only numbers) by each character up to four characters (numbers).

The idea is that brace expansions happen before pathname expansion. The brace expansion will convert and expand the ?{,?{,?{,?}}}.script.sh to

?.script.sh ??.script.sh ???.script.sh ????.script.sh

And then, the pathname expansion will find all file that match each pattern sorting each pattern in turn.

If none of the options above are a solution, you will need to use sort:

printf '%s\n' *.script.sh | sort -n | xargs echo

Which becomes even more complex if there is a folder prefix:

printf '%s\n' folder/*.script.sh | sort -n -k 1.8 | xargs echo

Where the 8 is the number of characters (bytes) in the word folder and the following / plus one (1).

You will need to replace the echo with sh to execute each script. This will work correctly if no file name contains newlines.

If it is possible that filenames may contain newlines, use this:

printf '%s\0' folder/*.script.sh | sort -zn -k 1.8 | xargs -0 -I{} echo '{}'

Again, replace the echo with a sh (or bash) to execute the scripts.

You must log in to answer this question.

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