30

I need to rename 45 files, and I don't want to do it one by one. These are the file names:

chr10.fasta         chr13_random.fasta  chr17.fasta         chr1.fasta          chr22_random.fasta  chr4_random.fasta  chr7_random.fasta  chrX.fasta
chr10_random.fasta  chr14.fasta         chr17_random.fasta  chr1_random.fasta   chr2.fasta          chr5.fasta         chr8.fasta         chrX_random.fasta
chr11.fasta         chr15.fasta         chr18.fasta         chr20.fasta         chr2_random.fasta   chr5_random.fasta  chr8_random.fasta  chrY.fasta
chr11_random.fasta  chr15_random.fasta  chr18_random.fasta  chr21.fasta         chr3.fasta          chr6.fasta         chr9.fasta         
chr12.fasta         chr16.fasta         chr19.fasta         chr21_random.fasta  chr3_random.fasta   chr6_random.fasta  chr9_random.fasta
chr13.fasta         chr16_random.fasta  chr19_random.fasta  chr22.fasta         chr4.fasta          chr7.fasta         chrM.fasta

I need to change the extension ".fasta" to ".fa". I'm trying to write a bash script to do it:

for i in $(ls chr*)

do

NEWNAME = `echo $i | sed 's/sta//g'`

mv $i $NEWNAME

done

But it doesn't work. Can you tell me why, or give another quick solution?

Thanks!

3 Answers 3

45

Several mistakes here:

  • NEWNAME = should be without space. Here bash is looking for a command named NEWNAME and that fails.
  • you parse the output of ls. this is bad if you had files with spaces. Bash can build itself a list of files with the glob operator *.
  • You don't escape "$i" and "$NEWNAME". If any of them contains a space it makes two arguments for mv.
  • If a file name begins with a dash mv will believe it is a switch. Use -- to stop argument processing.

Try:

for i in chr*
do
  mv -- "$i" "${i/%.fasta/.fa}"
done

or

for i in chr*
do
  NEWNAME="${i/%.fasta/.fa}"
  mv -- "$i" "$NEWNAME"
done

The "%{var/%pat/replacement}" looks for pat only at the end of the variable and replaces it with replacement.

Sign up to request clarification or add additional context in comments.

11 Comments

@Chris Dodd: taking good habits is though so useful afterwards.
One man's virtue is another man's vice -- Encouraging the use of spaces in filenames (or files that begin with -) is not a good thing.
Why is it not a good thing? Because programmers don't always correctly handle them? Ask the end users of computer workstations to remove all spaces, dashes, and non-alphanumeric characters from their filenames and spot their reaction :) As programmers it is our job to adapt to the possibilities of the systems we work on. As for files that begin with - why couldn't I name a file starting with a negative number for instance?
What does mv -- do? I've found it elsewhere but can't figure out what it does.
@Josh -- signifies end of option parsing. Therefore, if you have a file named -i for example, mv -- -i … will work because -i will not be interpreted as a switch.
|
14
for f in chr*.fasta; do mv "$f" "${f/%.fasta/.fa}"; done

5 Comments

althought this would work with the given data, what about spaces in files, or files that contain .fasta in their filename and not only as their extension ? many things can go wrong here
fixed use of /% before I even got to post the above comment ;)
Ok, I added the quotes even though they almost certainly aren't needed, given the OP's example. There also aren't likely any spurious periods in the names.
@Chris Dodd: so, now your answer is very similar to mine :) And always quoting is taking good habits. I used to use them lazily and one day came the disaster.
Removed downvote since files with spaces issue is fixed. Always use best practices when teaching others!
7

If you have the rename command, you can do:

rename .fasta .fa chr*.fasta

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.