1

Say I have a folder which contains files like this: a constant prefix and then an underscore and some description which is different for every file:

constantnamehere_description1.doc
constantnamehere_description2.doc
.
.
etc 

Here description1, description2 etc just symbolized the different descriptions and not the actual number 1,2 etc..

How can I rename these files to just this?

constantnamehere1.doc
constantnamehere2.doc
.
.
etc 

Here the numbers 1,2,..,etc symbolize the actual sequential ending that i want my files to have after the renaming. The sequential ending (1,2,3,...,end) is very important.

Till now I have tried:

for i in *.doc; do mv "$i" "{i/_*.doc/ .doc}"; done

example actual file names

1003407_cc_1.vtk
1003407_cc_2.vtk
1003407_cc_3.vtk
1003407_cv.left.right.vtk
1003407_thalamo_frontal.left.vtk

I want to be like:

1003407_1.vtk
1003407_2.vtk
1003407_3.vtk
1003407_4.vtk
1003407_5.vtk

To make it extremely clear: I want everything to be removed after the first underscore and to be replaced with sequential numbers keeping the ".vtk" extension of the file

Michael Jaros
  • 4,586
  • 1
  • 22
  • 39
azal
  • 1,210
  • 6
  • 23
  • 43
  • Does the order of the files matter? – Michael Jaros Mar 04 '15 at 15:25
  • yes. It would be preferred to stay unchanged – azal Mar 04 '15 at 15:26
  • 1
    But your question states that there is no such order at the beginning because the numbers are actually just placeholders for different desriptions. So how can it remain unchanged? :) I meant, does it matter which file is number 1, number 2 and so on? – Michael Jaros Mar 04 '15 at 15:27
  • The way you put it no. I just meant that i want the operation every time to give the same "random" result concerning the numbering. Because i will perform it to a lot of folders which contain the same files, so after the operation, i want the correspondence to still apply – azal Mar 04 '15 at 15:32
  • Ok, in that case you should be fine with my solution posted below because Bash will replace the `*` "with an alphabetically sorted list of file names matching the pattern" (from `bash(1)`). – Michael Jaros Mar 04 '15 at 15:36

3 Answers3

1

Using the an answer to Capturing Groups From a Grep RegEx, we can generate a regex for these file names and then rename by using the captured groups:

$ regex="([^_]*)_[^0-9]*([0-9]*).([a-z]*)"
$ for f in *doc
do 
    [[ $f =~ $regex ]]
    echo "mv $f --> ${BASH_REMATCH[1]}${BASH_REMATCH[2]}.${BASH_REMATCH[3]}"
done

The regex says: get everything up to _, then expect some characters until a digit is found. Catch that set of digits and then expect a dot followed by the extension.

Community
  • 1
  • 1
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • i'll give it a try and i ll get back at you – azal Mar 04 '15 at 15:14
  • it works fine but it doesn't put the number 1,2,3 etc at the end of constantnamehere – azal Mar 04 '15 at 15:18
  • @gelazari You are right, I didn't notice this before. Just completely rewrote the answer. – fedorqui Mar 04 '15 at 15:31
  • check now my edit at the bottom with actual file names – azal Mar 04 '15 at 15:40
  • 1
    @gelazari So now, after all the attempts we've been doing, you come up with some different approach: apparently, your input files do not have a number in there, whereas you did state that in the initial question. Make your mind clear and indicate what you want, because I am not going to update my answer anytime you come up with a different idea. – fedorqui Mar 04 '15 at 15:47
  • some of them do have a number at the end but some don't. Thats why i posted actual names. – azal Mar 04 '15 at 15:48
  • @gelazari You should have said that beforehand. It is tiring to keep updating the answer and I am not going to do it anymore. – fedorqui Mar 04 '15 at 15:52
  • 1
    In simple terms I want everything to be removed after the first underscore and to be replaced with sequential numbers keeping the ".vtk" extension of the file – azal Mar 04 '15 at 15:52
  • @gelazari check the first version of the answer: http://stackoverflow.com/revisions/28857893/1 It should be trivial to get your desired output from that version, you just need to add the counter. – fedorqui Mar 04 '15 at 15:58
  • @MichaelJaros i voted you up guys but i solved it with my way. thank you – azal Mar 04 '15 at 16:18
1

Use rename:

i=1
for file in *_*.vtk
do 
  rename "s/_[^.]*/${i}/" "$file"
  i=$(( i + 1 ))
done

This removes everything between the underscore and the first . from all files matching the *_*.vtk pattern. If your filenames contain more than one ., the pattern needs to be adapted.

EDIT: Solution modified according to modified question.

Michael Jaros
  • 4,586
  • 1
  • 22
  • 39
  • how can it be modified to add also 1,2,3,etc at the end of the name? – azal Mar 04 '15 at 15:29
  • I've just added the numbering. Now I have used some Bash too in addition to `rename`. It's still not too complex. – Michael Jaros Mar 04 '15 at 15:33
  • It looks quite risky to add the numbers sequentially, not very sure if this matches the OP requests – fedorqui Mar 04 '15 at 15:34
  • check now my edit at the bottom with actual file names – azal Mar 04 '15 at 15:40
  • @gelazari: Is it important to preserve the number in the variable part of the filename if there is any? – Michael Jaros Mar 04 '15 at 15:45
  • @fedorqui: I may have assumed too much, but if I read the comments on the question, this looks like what the OP wants to me. Maybe after my last question we will know. – Michael Jaros Mar 04 '15 at 15:47
  • no. I just want them to have sequential numbers after the constantPrefix but of course, if i perform the same operation in different folders containing the same set of files, i want them to rename all the files exactly with the same way every time. – azal Mar 04 '15 at 15:47
  • Ok, then the sequential numbering in my code should meet your requirements. Bash performs wildcard (e.g. `*`) expansion alphabetically, so the result should be always the same with the same set of files. – Michael Jaros Mar 04 '15 at 15:49
  • @MichaelJaros is there any different way using mv instead of rename? I want to perform the operation also on a macintosh – azal Mar 04 '15 at 15:53
  • 1
    @gelazari: Sure there is, but it needs a different approach and I wish you had given me this little information before letting me modify the `rename` approach 10 times :( Unfortunately I have to attend to something else now, but I'm sure some of the other members can help. I'll suggest to retag for Mac, maybe that helps. – Michael Jaros Mar 04 '15 at 16:02
1

I solved it like this:

i=0; 
for file in *.vtk; do mv "${file}" 100307_"${i}".vtk; i=$((i+1)); done
azal
  • 1,210
  • 6
  • 23
  • 43