1
$\begingroup$

I have 200 .vcf files in a folder with long names like

LP6005409-DNA_E03_vs_LP6005408-DNA_E03.snp.pass.vcf

How can I change the name of each file to, for example A1.vcf ....A200.vcf?

Renaming these files manually takes ages, help please.

> file.rename(list.files(pattern = "vcf"), paste0("A",1:length(list.files(pattern = ".vcf")),".vcf"))
Error in file.rename(list.files(pattern = "vcf"), paste0("A", 1:length(list.files(pattern = ".vcf")),  : 
  'from' and 'to' are of different lengths


[fi1d18@cyan01 new]$ for i in *.vcf; do echo mv $i A${k}.vcf ; k=`echo "1+${k}" | bc`; done
mv LP2000325-DNA_A01_vs_LP2000317-DNA_A01.snp.pass.vcf A.vcf
(standard_in) 2: syntax error
mv LP6008031-DNA_A04_vs_LP6008032-DNA_D03.snp.pass.vcf A.vcf
(standard_in) 2: syntax error
[fi1d18@cyan01 new]$ for i in *.vcf; do mv $i A${k}.vcf ; k=`echo "1+${k}" | bc`; done
(standard_in) 2: syntax error
mv: try to overwrite `A.vcf', overriding mode 0500 (r-x------)?
$\endgroup$
5
$\begingroup$

just to complete your question, you can do it in R in one line.

After setting the directory as your working directory, just type the following:

file.rename(list.files(pattern = "vcf"), paste0("A",1:length(list.files(pattern = ".vcf")),".vcf"))

Maybe you can try file.rename(list.files(pattern = ".vcf"), paste0("A",1:length(list.files(pattern = ".vcf")),".vcf")). Also, if there is still an error, can you post the output of list.files(pattern = ".vcf") just to see the structure of your files in folder (maybe one file has a weird name not detected by the pattern).

$\endgroup$
0
9
$\begingroup$

Use perl-rename. This is usually called rename on Debian-based systems like Ubuntu or Mint, and perl-rename or prename on others. Assuming you have it as rename, you can simply do:

rename -n 's/.*\.vcf/"A" . ++$c . ".vcf"/e' *snp.pass.vcf

The -n causes rename to only print what it would do, without doing anything. So once you make sure it does what you want, run the command again without the -n.

$\endgroup$
2
  • $\begingroup$ On a Mac, you may need to install it first. Use brew install rename or use zmv in zsh (not bash) shell: superuser.com/q/152627 $\endgroup$ Nov 11 '19 at 18:37
  • 2
    $\begingroup$ @TimurShtatland note that there are many renames in the Linux world, just to keep things interesting ;) $\endgroup$
    – terdon
    Nov 11 '19 at 18:42
3
$\begingroup$

EDIT:

(Based on the comments by @terdon, with minor changes)

Try this Perl one-liner. It is recommended for general use, even if your file names contain "unexpected" characters such as newlines.

perl -e 'for ( 0..$#ARGV ) { rename $ARGV[$_] => "A@{[ $_ + 1 ]}.vcf"; } ' *pass.vcf

Here, -e tells perl to look for code on the command line instead of a file with the script. @ARGV is the array of the command line arguments, here, files with old names.

for ( 0..$#ARGV ) { ... } loop goes through the indexes of elements of this array, assigning each implicitly to $_. The first argument to rename is the old file name: $ARGV[$_]. Instead of the comma separator of the method arguments I use => synonym for clarity in this method call.

The new file name is the second argument. @{[ ... ]} inside the double quotes is the Perl idiom to evaluate the expression inside, which is $_ + 1, to make the file numbering start with 1. If you don't care about this, it is easier to make it start with 0: just use "A$_.vcf", or, better, "A${_}.vcf". The last form needs to be used for cases like this: "A${_}pass.vcf" to prevent Perl from treating $_pass as a variable, where $_ is intended.

DEPRECATED:

Use the one-liner below when you are sure that the old file names do not have "unexpected" characters such as newlines. It is not for general use, see: Why you shouldn't parse the output of ls.

It will work with the example shown by the OP. It also works with blanks and tabs in the file names, but it breaks when file names have newlines.

The (deprecated) Perl one-liner:

ls *.pass.vcf | perl -lne 'rename $_, "A$..vcf";'

Here, ls | lists all files with old names, one per line and passes the stdout into stdin of the next command, which is the Perl one line script. -l removes the new lines from the input. -n reads the input one line at a time. These are all commonly used command line Perl options.

In the one liner script, $_ is the line read from stdin, and $. is the line number.

$\endgroup$
1
  • $\begingroup$ That is a slick perl one liner $\endgroup$
    – M__
    Nov 11 '19 at 2:11
3
$\begingroup$

If your filenames do not contain blank spaces, you can do it with a for-loop in bash:

Make a test run with echo so that the command is only printed but not yet executed:

for i in *.vcf; do echo mv $i A${k}.vcf ; let k++ ; done

And if the result looks good remove the echo statement to execute the mv commands:

for i in *.vcf; do mv $i A${k}.vcf ; let k++ ; done
$\endgroup$
3
  • $\begingroup$ Sorry I tried your code and I got error mentioned in the main post $\endgroup$
    – Exhausted
    Nov 12 '19 at 10:32
  • 1
    $\begingroup$ @Angel note that there is no reason to use bc even if you do choose to do it this way. ((k++)) or k=$((k+1)) or let k++ all work to increment the value of a shell variable: k=0; while [[ $k -lt 10 ]]; do echo $k; ((k++)); done. Alternatively: for((k=0; k<=10;k++)); do echo $k; done. $\endgroup$
    – terdon
    Nov 14 '19 at 13:27
  • $\begingroup$ Thanks for the comment! $\endgroup$
    – Soren
    Nov 15 '19 at 20:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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