简体   繁体   中英

Bash command-line to rename wildcard

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM