LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   rename files after reading source file (https://www.linuxquestions.org/questions/linux-newbie-8/rename-files-after-reading-source-file-4175512797/)

tofayel001 07-30-2014 10:23 PM

rename files after reading source file
 
Hi everyone,

I have a directory full of over a thousand files and the names are bit long (and no pattern found in the naming style). I would like to simplify the filenames. For eg:

Bioimage_23335989_Data_22317866_22317867_20140723_1002.pdb
Bioimage_22335990_Data_22318490_22318491_20140723_1009.pdb
Bioimage_23835970_Data_22317866_22317867_20140723_1005.pdb

.....and so on !

I have made a simple text file (filelist.txt) which reads like this:
1.pdb Bioimage_23335989_Data_22317866_22317867_20140723_1002.pdb
2.pdb Bioimage_22335990_Data_22318490_22318491_20140723_1009.pdb
3.pdb Bioimage_23835970_Data_22317866_22317867_20140723_1005.pdb

.....and so on !

Can anybody provide me with a script (awk, sed , etc) which would read the source file and rename the files accordingly? I could get similar scripts else where but nothing seems to work for me. Any kind of help would be highly appreciated.

notKlaatu 07-30-2014 10:52 PM

You don't need the text file unless the numbers actually mean something. If you just need them to be sequential, do this:

Code:

ls -1 | cat -n | while read n f; do mv "$f" "$n.txt"; done
If you do have some method to the nomes in the text file, then you can use it this way:

Get rid of the space delimiter in your new file name listing:

Code:

cat file.txt | tr ' ' ':' > new.txt
And then use the new file to rename the pdb files:

Code:

for f in $(< new.txt) ; do mv $(echo $f | cut -f 2 -d":") $(echo $f | cut -f 1 -d":") ; done

Yeah there's certainly a more elegant way to do it with awk, but that is what popped into my head and it works :-)

eklavya 07-31-2014 01:19 AM

If you simply want to rename the all files of a directory in numerical order, you do not need text file. A simple for loop can do this.
Suppose you have a directory which contains only files like
Code:

Bioimage_23335989_Data_22317866_22317867_20140723_1002.pdb
Bioimage_22335990_Data_22318490_22318491_20140723_1009.pdb
Bioimage_23835970_Data_22317866_22317867_20140723_1005.pdb
Bioimage_23335989_Data_22317866_22317867_20140724_1002.pdb
Bioimage_22335990_Data_22318490_22318491_20140725_1009.pdb
Bioimage_23835970_Data_22317866_22317867_20140726_1005.pdb
Bioimage_23335989_Data_22317866_22317867_20140723_1003.pdb
Bioimage_22335990_Data_22318490_22318491_20140723_1004.pdb
Bioimage_23835970_Data_22317866_22317867_20140723_1006.pdb
Bioimage_23835970_Data_22317866_22317867_20140723_2006.pdb

and you want to rename them like
Code:

1.pdb
2.pdb
3.pdb
4.pdb
5.pdb
6.pdb
7.pdb
8.pdb
9.pdb
10.pdb

First enter into the directory using cd and run the command
Code:

j=0; for i in *.pdb; do j=`expr $j + 1`; mv $i $j.pdb; done
It will rename all the pdb files.

If there are all types of files in a directory like jpg, txt, pdb and many more and you want to rename all in numerical order with their respective file extension, First enter into the directory using cd and run the command
Code:

j=0; for i in *; do ext=$(echo $i |awk -F . '{if (NF>1) {print "."$NF}}'); j=`expr $j + 1`; mv $i $j$ext; done
It will rename all files.

But if you want that every file should be renamed with the name mentioned in text file in same row. First enter into the directory using cd and run the command.
Path of text file should be correct.
Code:

IFS=$'\n'; lst=$(cat /path/of/filelist.txt); for i in $lst; do mv `echo $i | awk '{print $2}'` `echo $i | awk '{print $1}'`; done
I considered the format of your text file what you mentioned above.

evo2 07-31-2014 02:04 AM

Hi,

assuming bash, zsh or similar, no need for `` and expr try
Code:

i=1 ; for f in *.pdb ; do echo mv $f $((i++)).pdb ; done
It gets a little messier if you want to zero pad the filenames so they sort properly...
Code:

i=1 ; for f in *.pdb ; do echo mv $f $(printf "%05d.pdb" $i) ; ((i++)) ; done
Evo2.

PS. The "echo" is in there for testing.

pan64 07-31-2014 02:14 AM

OP told he has thousands of files. Using backtick in the solution will fork new process, all of these tips will fork several thousand processes. That looks very inefficient for me.
Code:

instead of:
for f in $(< new.txt) ; do mv $(echo $f | cut -f 2 -d":") $(echo $f | cut -f 1 -d":") ; done
do:
for f in $(< new.txt) ; do mv ${f##*:} ${f%:*}; done      # using : as separator
or for f in $(< new.txt) ; do mv ${f##* } ${f% *}; done  # using the original space

(late...)

tofayel001 07-31-2014 03:36 AM

Thank you all for the kind answers. I did want my filenames to be simplified but also wanted to keep track of "who is who", ie, simply renaming them (randomly) 1.pdb, 2.pdb, 3.pdb... doesn't work for me ! Therefore, I would always need to use the source file to let the program know what new name has to be assigned. So, codes provided by notKlaatu and pan64 work very well for me. But I appreciate you all for your time and kindness !

tofayel001 07-31-2014 04:27 AM

Appending numbers with file extension to each line in a textfile
 
Hi everybody,

I have a directory full of over thousand files. For eg.- Hello.pdb, Image.pdb, Biology.pdb, ....etc. I would like to enlist all of them in a file in a manner like this:

Hello.pdb
Image.pdb
Biology.pdb

.....and so on !

and I would like to get a file which would read:

1.pdb:Hello.pdb
2.pdb:Image.pdb
3.pdb:Biology.pdb

.....and so on !

It looks easy but I am not able to get a suitable code for this. Any help would be highly appreciated !

pan64 07-31-2014 04:31 AM

you need to modify only the solution you got from evo2:
Code:

was:
i=1 ; for f in *.pdb ; do echo mv $f $(printf "%05d.pdb" $i) ; ((i++)) ; done
what you need (for example):
i=1 ; for f in *.pdb ; do echo "$i.pdb $f"; ((i++)) ; done


tofayel001 07-31-2014 04:53 AM

Quote:

Originally Posted by pan64 (Post 5212422)
you need to modify only the solution you got from evo2:
Code:

was:
i=1 ; for f in *.pdb ; do echo mv $f $(printf "%05d.pdb" $i) ; ((i++)) ; done
what you need (for example):
i=1 ; for f in *.pdb ; do echo "$i.pdb $f"; ((i++)) ; done


Thank you for your answer, but it gives me the following output in the terminal:

1.pdb *.pdb

chrism01 07-31-2014 05:20 AM

This variation works for me
Code:

i=1 ; for f in *.pdb ; do echo "${i}.pdb:${f}" >>pdb.lis; ((i++)) ; done

tofayel001 07-31-2014 05:38 AM

Quote:

Originally Posted by chrism01 (Post 5212435)
This variation works for me
Code:

i=1 ; for f in *.pdb ; do echo "${i}.pdb:${f}" >>pdb.lis; ((i++)) ; done

Thank you for your answer. But, your code creates a new file namely 'pdb.lis' in the directory which reads:

1.pdb:*.pdb

pwalden 07-31-2014 02:48 PM

Assuming we are talking bash here, looks like you may have pattern matching turned off.

Do you have a the env variable GLOBIGNORE set? Do you have a -f or -o noglob bash options set anywhere? (like in an alias?)

Tinkster 07-31-2014 03:24 PM

I merged your two closely related threads and ask that you stick to one thread per topic.

Thanks.

evo2 07-31-2014 07:00 PM

Hi,

Quote:

Originally Posted by tofayel001 (Post 5212443)
Thank you for your answer. But, your code creates a new file namely 'pdb.lis' in the directory which reads:

1.pdb:*.pdb

Are you sure you are in the directory containing al the .pdb files? Eg do you see them when you run ls?

Evo2.

tofayel001 08-07-2014 07:26 AM

Thank you everybody for answering and I apologise for replying so late. I have no idea what was going wrong but when I tried the same codes on another computer, it worked ! With little modifications I could run each of your codes, successfully. Could be some silly mistake from my side, but couldn't figure out so far. @Tinkster: Noted. Thanks !


All times are GMT -5. The time now is 01:36 AM.