0

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.

graille
  • 113
  • 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 … –  Nov 16 '18 at 18:52
  • There are no leading zero, and N can have more than one digit. – graille Nov 16 '18 at 18:54
  • Read man run-,parts. – waltinator Nov 16 '18 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? –  Nov 16 '18 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. – don_crissti Nov 16 '18 at 20:40
  • So, you assume user intentions. Why don't you ask? It's easy to do that, let me do it ! @don_crissti –  Nov 16 '18 at 20:42
  • @graille Should the solution be a bash script or a shell script ? –  Nov 16 '18 at 20:43
  • @Isaac - this is getting quite entertaining... though for obvious reasons this has to end... Anyway, I'm not the one who makes assumptions here (like assuming OP wants to add some prefix named folder or that the solution has to be bash-specific) – don_crissti Nov 16 '18 at 20:52
  • It is You who is assuming that the OP made the mistake of using a bash tag without any indication or clue. Without even asking. And now you try to confuse by expanding to more (unrelated) issues. No, this is not entertaining, not any. –  Nov 16 '18 at 21:00

2 Answers2

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
do
  printf "Executing script: %s\n" "$script"
  ./"$script"
done

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)
do
  printf "Executing script: %s\n" "$script"
  ./"$script"
done

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.

don_crissti
  • 82,805
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
  • Ideally OP would zero-pad the file names, then using a simple glob like ./* should work with any shell... – don_crissti Nov 16 '18 at 19:31
  • Thanks for the edit, don; I'm still experimenting with zsh. – Jeff Schaller Nov 16 '18 at 19:32
  • No problem. You could also use a function as shown here – don_crissti Nov 16 '18 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 Nov 16 '18 at 19:38
  • In zsh, how do you add a folder (as requested in the OP) prefix? –  Nov 16 '18 at 19:46
  • @Isaac - Which part of the post exactly requires that a prefix should be added ? Could you quote that part ? – don_crissti Nov 16 '18 at 19:52
  • 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 –  Nov 16 '18 at 19:53
  • @don_crissti The title … scripts from a **folder** … and three other places in the question. But I have added a comment with the zsh solution as well (I believe). Have a nice day!!. –  Nov 16 '18 at 19:56
  • Thanks, @isaac, for pointing out the simpler (n)! I approached it narrowly, wanting to specify exactly what was being sorted (specifically because I was avoiding the shell's natural glob/sort order). – Jeff Schaller Nov 16 '18 at 20:01
  • Re: the folder, the Question read to me like the OP had a master script and these sub-scripts in the folder, so the presumption was that the OP would cd to this folder before executing the remainder. – Jeff Schaller Nov 16 '18 at 20:02
  • Re: folder, yes, that would be a sensible thing that the OP could do (I mean to cd to the folder) but users never cease to amaze me. :-) … –  Nov 16 '18 at 20:05
2

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"
done

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.