In my /opt/myapp
dir I have a remote, automated process that will be dropping files of the form <anything>-<version>.zip
, where <anything>
could literally be any alphanumeric filename, and where <version>
will be a version number. So, examples of what this automated process will be delivering are:
fizz-0.1.0.zip
buzz-1.12.35.zip
foo-1.0.0.zip
bar-3.0.9.RC.zip
etc. Through controls outside the scope of this question, I am guaranteed that only one of these ZIP files will exist under /opt/myapp
at any given time. I need to write a Bash shell command that will rename these files and move them to /opt/staging
. For the rename, the ZIP files need to have their version dropped. And so /opt/myapp/<anything>-<version>.zip
is renamed and moved to /opt/staging/<anything>.zip
. Using the examples above:
/opt/myapp/fizz-0.1.0.zip
=> /opt/staging/fizz.zip
/opt/myapp/buzz-1.12.35.zip
=> /opt/staging/buzz.zip
/opt/myapp/foo-1.0.0.zip
=> /opt/staging/foo.zip
/opt/myapp/bar-3.0.9.RC.zip
=> /opt/staging/bar.zip
The directory move is obvious and easy, but the rename is making me pull my hair out. I need to somehow save off the <anything>
and then re-access it later on in the command. The command must be generic and can take no arguments.
My best attempt (which doesn't even come close to working) so far is:
file=*.zip; file=?; mv file /opt/staging
Any ideas on how to do this?
for file in *.zip; do
[[ -e $file ]] || continue # handle zero-match case without nullglob
mv -- "$file" /opt/staging/"${file%-*}.zip"
done
${file%-*}
removes everything after the last -
in the filename. Thus, we change fizz-0.1.0.zip
to fizz
, and then add a leading /opt/staging/
and a trailing .zip
.
To make this more generic (working with multiple extensions), see the following function (callable as a command; function body could also be put into a script with a #!/bin/bash
shebang, if one removed the local
declarations):
stage() {
local file ext
for file; do
[[ -e $file ]] || continue
[[ $file = *-*.* ]] || {
printf 'ERROR: Filename %q does not contain a dash and a dot\n' "$file" >&2
continue
}
ext=${file##*.}
mv -- "$file" /opt/staging/"${file%-*}.$ext"
done
}
...with that function defined, you can run:
stage *.zip *.txt
...or any other pattern you so choose.
f=foo-1.3.4.txt
echo ${f%%-*}.${f##*.}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.