Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I have a grader for COCI (a competitive programming contest) that reads input files (txt[number].in), compiles and runs a code (txt.cpp) and matches the result with an output file (txt[number].out). The problem is, COCI problem's input files have format (txt.in.1), (txt.in.2), (txt.in.3) etc and similar names for output files.

I need to change the extensions of the input files from txt.in.[number] to txt[number].in. (Need to do the same for the output files as well)

Can anyone help me with this?

I'm currently using 13.04 Ubuntu.

share|improve this question
add comment

4 Answers 4

up vote 3 down vote accepted

Using the terminal, I think this is the easiest way:

mmv -v "*.in.*" "#1#2.in"

Here is a test:

$ ls
txt.in.1  txt.in.2  txt.in.3
$ mmv -v "*.in.*" "#1#2.in"
txt.in.1 -> txt1.in : done
txt.in.2 -> txt2.in : done
txt.in.3 -> txt3.in : done
$ ls
txt1.in  txt2.in  txt3.in

By default, mmv is not installed in Ubuntu, but you can install it from terminal using the following command:

sudo apt-get install mmv

See man mmv for more info.

share|improve this answer
    
Thanks and sorry for the late reply. I'm away from home and hardly have access to internet and ubuntu. But this looks like its just what I want. I'll get back to as soon as I get to try this. –  Labib666 Oct 10 '13 at 11:31
    
Hi, sorry to bother you again. I just changed the question a bit. Since I dont know how mmv works, I need your help to know how I have to make the change. –  Labib666 Oct 11 '13 at 6:42
    
@Labib666 Ok, see my new edits. But keep in mind: It's not a good practice to change your question after you received your answer. Use Ask Question button if you have new questions. –  Radu Rădeanu Oct 11 '13 at 6:51
    
Thanks again. I'll try not to do such mistakes from the next time. I'm fairly new here. So, just learning from errors. –  Labib666 Oct 11 '13 at 12:13
    
@Labib666 Ok. So, have you seen my new edits at the answer? –  Radu Rădeanu Oct 11 '13 at 12:22
show 4 more comments

If it is okay that a file.in.1 becomes file.in.1.in, then this will do

rename 's/$/.in/' *

If you think the two in's are ugly, then do

rename 's/\.in(\.\d+)$/$1.in/' *

Pass the -n option to perform a dry run.

share|improve this answer
2  
You can make it a little simpler than that I think e.g. s/(\.in)(\.\d+)/$2$1/. Also for safety it's good practice to mark the end of the option list i.e. rename -nv -- 's/(\.in)(\.\d+)/$2$1/' * (just in case there happen to be any files starting with -) –  steeldriver Oct 4 '13 at 12:44
1  
@steeldriver Good point, the regexp isn't pinned at ^, so the first can also be reduced to 's/$/.in/'. And the second can be simplified even further. Will fix the solution. –  zwets Oct 4 '13 at 18:15
    
I knew this one. Unfortunately .in and .out files need to have same names. So it doesn't really help. Thanks for trying though :) –  Labib666 Oct 10 '13 at 11:25
add comment

This script will copy all files in the working dir, that match *.in.*

#!/bin/bash
for i in $(ls *.in.*)
do
    target=$(echo ${i} | awk -F'.' '{ print $1$3"."$2 }')
    cp ${i} ${target}
done
share|improve this answer
    
I'll get back to you after I try it on my computer. Thanks. :) –  Labib666 Oct 11 '13 at 12:37
add comment

A version using rename that works for your revised format would be

rename -- 's/(\.in|\.out)\.(\d+)/$2$1/' *

e.g.

$ ls
txt.in.1  txt.in.2  txt.in.3  txt.out.1  txt.out.2  txt.out.3
$
$ rename -nv -- 's/(\.in|\.out)\.(\d+)/$2$1/' *
txt.in.1 renamed as txt1.in
txt.in.2 renamed as txt2.in
txt.in.3 renamed as txt3.in
txt.out.1 renamed as txt1.out
txt.out.2 renamed as txt2.out
txt.out.3 renamed as txt3.out
share|improve this answer
    
Thanks for the help. :) It would be helpful if you tell me how the commands would look if I was changing extension of txt.in.[number][alphabet] to txt[number][alphabet].in. I just heard that there were extensions like these as well. :( –  Labib666 Oct 11 '13 at 17:50
    
Well you could change the \d+ (one or more digits) by \w+ (one or more from the set [a-zA-Z0-9_] in any order) although that would match things like 2c3, aBa as well; if you need to match EXACTLY one or more digits optionally followed by one or more alphabetical letters, change (\d+) to (\d+([[:alpha:]]+)?) or ([[:digit:]]+([[:alpha:]]+)?) - you should probably look up some information about perl regular expressions and try to figure out exactly what you need yourself –  steeldriver Oct 11 '13 at 18:29
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.