Using glob on CLI that does not support variadic arguments
Recently I need to use sops
to encrypt and decrypt a set of secret files for deploying Kubernetes workload using the GitOps approach. All of these files has an extension of sops
, for example secret.sops.yaml
. For a simple task like this, I was expecting everything can be done in a single line using glob.
sops --encrypt **/*.sops.* # encrypt all files with a sub extension of sops
Unfortunately, sops
cannot handle variadic arguments. Only the first argument is handled, and the rest are simply ignored. As a glob will be expanded by the shell into a space separated string, and array in shell can be created based on a space separated string as well, I wonder if I can turn a glob into an array, and then iterate all its items in a loop.
I started off by verifying that I can build an array from glob, using a really simple example.
touch foo.md bar.md
arr=(*.md)
echo "${#arr[@]}" # getting the length of the array, and it prints 2
And then, I tried to run a for
loop on this array, and it worked.
for file in $list[@]; do echo "$file"; done # foo.md bar.md
I thought I have reached an optimal solution already, until I found out that you can use for
loop without an array! We can use glob directly on a for
loop, and everything is nice and clean.
for file in *.md; do echo "$file"; done # foo.md bar.md
Allowing glob to fail gracefully
Everything seems to be working so far. I have then implemented my script in the actual project, and found out that my script will break when the glob pattern cannot match anything. I thought it would be expanded to an empty string, yet it exited right away.
After searching for a while, I found that you could set shopt -s nullglob
in bash and zsh and prevent an unmatched glob from exiting.