In a zsh I want to loop over all files in a configuration files' directory (/etc/myapp/) to source them. The files should be sourced in order and are named with two leading digits 10-early 40-middle 99-last. A user without write permission to /etc should be allowed to extend the list of files and override the global ones. This is done by creating a $HOME/.myapp directory. The user files should be sourced in order with the global files, i.e. /etc/myapp/10-early $HOME/.myapp/20-rightafter /etc/myapp/40-middle $HOME/.myapp/90-late /etc/myapp/99-last. A user should also be allowed to override global files, i.e. when $HOME/.myapp/99-last exists, then /etc/myapp/99-last should be skipped.

As answerded here and here, I create an array with all the config files and then use basename on the array (like here) to restrict it to the NN-lllll part and sort them. Eventually each file gets sourced from $HOME/.myapp if it exists there, and from /etc/myapp otherwise.

# https://stackoverflow.com/a/10981499
# https://unix.stackexchange.com/a/26825
thefiles=(/etc/myapp/* $HOME/.myapp/*(N))
# https://stackoverflow.com/a/9516801
uniquified=( $( for f in "${thefiles[@]}" ; do basename $f ; done | sort -V | uniq) )
for f in $uniquified
# -r checks if file exists and is readable
  if [[ -r $HOME/.myapp/$f ]]
    source $HOME/.myapp/$f
    source /etc/myapp/$f

Is there a more elegant solution and should I be aware of errors I need to catch?


You can combine sort -V | uniq into sort -uV.

Note that the -V flag of sort doesn't exist in BSD. Consider replacing it with -n if that's good enough.

The if inside the loop can be written more compactly as:

[[ -r $HOME/.myapp/$f ]] && source $HOME/.myapp/$f || source /etc/myapp/$f

You could also replace source with . which is equivalent.


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.