Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Reading filename using regexp in Bash

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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!

>Solution :

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 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
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading