I am writing a bash script that calls an external program which generates a zip file of the form ########.zip which the '#'s# can be any decimal digit. There is no way to predict what the digits will be.
So far I have been able to get by using the regexp [0-9][0-9]*zip for things like moving the zip file around and unzipping it. However, now I need to add a txt file to the archive under the directory name ######## where the digits are the same as the archive name. So, if the archive is 12345678.zip, I need to add the file 12345678/foo.txt.
The only way I can see to do this is to create the directory '12345678' and copy the file there and then add the directory to the archive. However I can't figure out how to get the name of the archive so that I can create the directory.
The best I could some up with was to use backticks to assign the output of ls -l to a variable and then parse that to get just the filename part. But there has to be an easier way?
I am using 7z as the zip utility if it matters.
Thanks!
What you're asking for is not a regex but a "glob expression". In particular, if you want to match any number of digits, this can be done with a bash feature called extended globbing, or "extglobs". Read more at https://wiki.bash-hackers.org/syntax/pattern#extended_pattern_language.
#!/usr/bin/env bash
# ^^^^- NOT sh
shopt -s extglob
for f in +([[:digit:]]).zip; do
digits=${f%.zip}
mkdir -p "$digits"
echo hello >"$digits/foo.txt"
zip "$f" "$digits/foo.txt"
done
In the parameter expansion digits=${f%.zip}
, we take .zip
off the end of the filename, and store the rest in the variable digits
.
Extending the above to work in a temporary directory and clean up after ourselves:
#!/usr/bin/env bash
# ^^^^- NOT sh
shopt -s extglob
olddir=$PWD
for f in +([[:digit:]]).zip; do
digits=${f%.zip}
tempdir="$(mktemp -d -t zipupdate.XXXXXX)"
(
cd "$tempdir" || exit
mkdir -p "$digits" || exit
echo hello >"$digits/foo.txt" || exit
zip "$olddir/$f" "$digits/foo.txt"
)
rm -rf "$tempdir"
done