1

[context] My script needs to replace semvers of multiple .car names with commit sha. In short, I would like that every dev_CA_1.0.0.car became dev_CA_6a8zt5d832.car

ADDING commit sha right before .car was pretty trivial. With this, I end up with dev_CA_1.0.0_6a8zt5d832.car

find . -depth -name "*.car" -exec sh -c 'f="{}"; \
mv -- "$f" $(echo $f | sed -e 's/.car/_${CI_COMMIT_SHORT_SHA}.car/g')' \;

But I find it incredibly difficult to REPLACE. What aspect of sed am I misconceiving trying this:

find . -depth -name "*.car" -exec sh -c 'f="{}"; \
mv -- "$f" $(echo $f | sed -r -E 's/[0-9\.]+.car/${CI_COMMIT_SHORT_SHA}.car/g')

or this

find . -depth -name "*.car" -exec sh -c 'f="{}"; \
mv -- "$f" $(echo $f | sed -r -E 's/^(.*_)[0-9\.]+\.car/\1${CI_COMMIT_SHORT_SHA}\.car/g')' \;
no matches found: f="{}"; mv -- "$f" $(echo $f | sed -r -E ^(.*_)[0-9.]+.car/1684981321531.car/g)

or multiple variants:

  • \ escaping (e.g. \\.)
  • ( and ) escaping (e.g. \() (I read somewhere that regex grouping with sed requires some care with ())

Is there a more direct way to do it?

Edit

$f getting in sed are path looking like

./somewhere/some_project_CA_1.2.3.car
./somewhere_else/other_project_CE_9.2.3.car
zar3bski
  • 2,773
  • 7
  • 25
  • 58

2 Answers2

1

You may use

sed "s/_[0-9.]\{1,\}\.car$/_${CI_COMMIT_SHORT_SHA}.car/g"

See the online demo

Here, sed is used with a POSIX ERE expression, that matches

  • _ - an underscore
  • [0-9.]\{1,\} - 1 or more digits or dots
  • \.car - .car (note that a literal . must be escaped! a . pattern matches any char)
  • $ - end of string.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Your answer / demo is clear but I am still getting the same error. I should have been more explicit about what is exactly piped in `sed` (see my edit). Maybe the problem is not `sed` *per se* but way I execute it – zar3bski Apr 30 '20 at 14:52
  • @zar3bski So, `./somewhere/some_project_CA.1.2.3.car` is your input? Then use `sed "s/\.[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\.car$/_${CI_COMMIT_SHORT_SHA}.car/"`, see [demo](https://ideone.com/GH1TDF). Or `sed -E "s/\.[0-9]+\.[0-9]+\.[0-9]+\.car$/_${CI_COMMIT_SHORT_SHA}.car/"` – Wiktor Stribiżew Apr 30 '20 at 14:55
  • Still the same so I think that `-exec sh -c` is messing with the instruction passed to `sed` (and with my brain: manes are actually `_1.0.7.car` not `.1.0.7.car`). I'll look for a more direct approach. Thanks for your instructing demos – zar3bski Apr 30 '20 at 15:06
  • 1
    @zar3bski Make sure you are using *double quoation marks* around the `sed` command, else, there won't be any variable expansion. – Wiktor Stribiżew Apr 30 '20 at 15:39
  • however, the value of `CI_COMMIT_SHORT_SHA` does not appear. I guess `-exec sh` does not inherit the variables from the shell that is calling him. But I can find a workarund (like looping with a `for`) – zar3bski Apr 30 '20 at 15:56
  • 1
    @zar3bski Also, check [Recursively rename files using find and sed](https://stackoverflow.com/q/4793892/3832970) – Wiktor Stribiżew Apr 30 '20 at 16:07
0

Can you try this :

export CI_COMMIT_SHORT_SHA=6a8zt5d832
find . -depth -name "*.car" -exec sh -c \
 'f="{}"; echo mv "$f" "${f%_*}_${CI_COMMIT_SHORT_SHA}.car"' \;

Remove echo once you are satisfied of the result.

Philippe
  • 20,025
  • 2
  • 23
  • 32