BASH – vasp2xyz, a script to extract coordinates from VASP

Users of VASP are often familiar with the struggles/hardships to easily visualize the coordinates from the output file [OUTCAR]. To that effect, I wrote the following script [with help at a crucial stage from Pat Krogel, CEC @ MTU]. It expects OUTCAR & POSCAR from a calculation to be in the same folder and when successfully completed, it results in – containing frame-by-frame [corresponding to each (optimization) step] XYZ co-ordinates of the system.

#! /bin/bash
# Script to extract the atomic positions (xyz) from 
# POSCAR & OUTCAR files of VASP and write them to a 
# file, to be used with Jmol, MolDen and such other
# third party programs
# First written: Gowtham, Tue, 22 Dec 2009 11:11:12 -0500
# Last modified: Gowtham, Tue, 22 Dec 2009 16:29:36 -0500
# Essential VASP Files
# If missing, quit the program
if [[ -e $POSCAR || -e $OUTCAR ]];
  echo "  $POSCAR & $OUTCAR found"
  echo "  ERROR : POSCAR &/or OUTCAR missing"
# Output Filename 
# If missing, quit the program
export OUTPUT=$1
if [ $# != 1 ]
  echo "  ERROR : OUTPUT_FILENAME Missing"
  echo "  Usage : OUTPUT_FILENAME"
# Delete scratch files
rm -f Final.tmp.*
rm -f $
# Atoms related information
# Extracted from POSCAR & OUTCAR
# Total number of atom types
# Pat Krogel: Tue, 22 Dec 2009 13:13:48 -050
declare -a ATOM_TYPE=(`sed -n '6 p' $POSCAR`)
# Total number of atoms
export ATOMS_TOTAL=0
export i=0
while [[ "$i" -lt "$ATOM_TYPE_TOTAL" ]]
  export iATOM_TYPE=${ATOM_TYPE[$i]}
  export i=`expr $i + 1`
# Atom labels
declare -a ATOM_LABEL=(`grep "POTCAR:" $OUTCAR | head -$ATOM_TYPE_TOTAL | awk '{print $3}' | sed -e 's/_.*//g'`)
# Print2Screen
  echo "  ERROR : Atom Type Total ($ATOM_TYPE_TOTAL) does NOT"
  echo "          match Atom Label Count ($ATOM_LABEL_COUNT)"
  echo "  Please make sure OUTCAR & POSCAR are from the same"
  echo "  system and calculation"
  echo "  Number of Atom Types   :" $ATOM_TYPE_TOTAL
  echo "  Atom Type              :" ${ATOM_LABEL[@]}
  echo "  Atom Type Count        :" ${ATOM_TYPE[@]}
  echo "  Total Number of Atoms  :" $ATOMS_TOTAL
  # ATOM_LABEL_2 is an array of atom labels
  # with each atom label appearing an appropriate
  # number of times, to a total of $ATOMS_TOTAL
  declare -a ATOM_LABEL_2
  export REPEAT=0
  export j=0
  while [[ "$j" -lt "$ATOM_TYPE_TOTAL" ]]
    export k=1
    while [[ "$k" -le "${ATOM_TYPE[$j]}" ]]
      export REPEAT=`expr $REPEAT + 1`
      export k=`expr $k + 1`
    export j=`expr $j + 1`
# echo ${ATOM_LABEL_2[@]}
# echo ${#ATOM_LABEL_2[@]}
  # Record the line numbers where coordinates are written
  # in OUTCAR. Actual coordinates begin 2 lines below
  # the recorded numbers
  grep -n "POSITION" $OUTCAR | sed -e 's/:/ /g' | sed -e 's/POSITION.*//g' > LINE_NUMBERS.tmp
  export FRAME_NUMBER=1
  while read START
    export START_HERE=`expr $START + 2`
    export END_HERE=`expr $START_HERE + $ATOMS_TOTAL - 1`
    echo "$ATOMS_TOTAL" >> $
    echo "# Frame Number: $FRAME_NUMBER" >> $
    sed -n "$START_HERE,$END_HERE p" $OUTCAR | awk '{printf "%12.8f %12.8f %12.8f\n", $1, $2, $3}' > Final.tmp.$FRAME_NUMBER
    export l=1
    while read X Y Z
      echo ${ATOM_LABEL_2[$l]} $X $Y $Z > Final.tmp.$FRAME_NUMBER.$l
      awk '{ printf "%-3s %12.8f %12.8f %12.8f\n", $1, $2, $3, $4 }' Final.tmp.$FRAME_NUMBER.$l >> $
      export l=`expr $l + 1`
    export FRAME_NUMBER=`expr $FRAME_NUMBER + 1`

Test case

If POSCAR and OUTCAR aren’t handily available for testing, one could download the following:





Resulting xyz file


xyz file visualized with Jmol

If you have suggestions to make this better/efficient, please do post them as comments.


14 Replies to “BASH – vasp2xyz, a script to extract coordinates from VASP”

  1. Hi….I already save the script with the name but I have some problem to execute the program….This is what happen when I want to use the program :

    [revival@localhost Program]$ vasp2xyz
    bash: vasp2xyz: command not found

    Could someone give me an answer about this???


    1. It is important [and often assumed] that you place these programs/scripts in one of the locations defined by PATH variable. You could check for this by running the command:

      echo $PATH

      One such common location for keeping user’s personal collection of scripts is ‘bin‘ folder within your $HOME directory. Be sure to change the permission of the downloaded script to 755 [or at least 700] by running the command:

      chmod 700

      Assuming that you are using the default shell [/bin/bash] for your login, you will need to add the following line to $HOME/.bashrc file:

      export PATH="$HOME/bin:$PATH"

      Save the file and run the command:

      . $HOME/.bashrc

      Once these [customary] steps are completed, you can call [or any such script stored in your ‘bin‘ folder] from just about any other folder.

      Hope this helps.

    2. Dear Gowtham,,,,thanks so much for your reply and I did like you told me,,,and this is the result :

      I change the mode of vasp2xyz
      [revival@localhost Program]$ chmod 700

      I put the bin path into the .bashrc
      [revival@localhost Program]$ vi ~/.bashrc

      #this is for

      export PATH=”$HOME/bin:$PATH”

      and then I try again to execute the and it doesn’t work

      [revival@localhost Program]$
      bash: command not found

      This is the $PATH

      [revival@localhost Program]$ echo $PATH

      Is there anything that I miss to do???? I’m sorry to ask a very basic question like this because I’m still a newbee in linux,,,,this is the first year for me to learn linux but I’m improving much after I read your reply

      Thanks so much Gowtham


    3. Dear Gowtham

      This is the result

      [revival@localhost bin]$ $HOME/bin/
      bash: /home/revival/bin/ /bin/bash^M: bad interpreter: No such file or directory

      I already put the file in bin folder,,,,how do you think Gowtham???


    4. Ok – I think I know the problem. The error message says /bin/bash^M. ^M indicates invisible Carriage Return character. To get rid of them, do the following:

      1. vi $HOME/bin/

      2. :g/CTRL+V+M/s///g

      CTRL+V+M means hold down the Control Key along with V & M

      3. :wq

      4. Then try $HOME/bin/

      And let me know if this works.

  2. Dear Gowtham

    I try like you told me and I find something strange

    [revival@localhost bin]$ vi $HOME/bin/

    then I type :g/CTRL+V+M/s///g

    Then I press my keyboard

    And it says :

    E486: Pattern not found: CTRL+V+M

    Then I save it :wq

    After that I try again

    [revival@localhost bin]$
    bash: /home/revival/bin/ /bin/bash^M: bad interpreter: No such file or directory

    for information,,,,,I’m using mandriva operating system,,,,I don’t know whether it always happens like this with mandriva

    So Gowtham,,,,how do you think???

    Thanks so much for helping a newbee like me


    1. Dear Gowtham

      I try it again

      I type g/CTRL+V+M/s///g

      CTRL+V+M means hold down the Control Key along with V & M
      and then I press Enter on my keyboard….This is the result :

      E486: Pattern not found: ^M

      So I save it again,,,,and then I type in command line

      [revival@localhost ~]$ $HOME/bin/
      bash: /home/revival/bin/ /bin/bash^M: bad interpreter: No such file or directory

      How do you think Gowtham???


    2. OK – the last trick in my bag is to try the following command:

      dos2unix $HOME/bin/

      and see if the command works.

      If not, then you are better off literally typing out the script.

    3. Dear gowtham

      I’m sorry to tell you bad result,,,,it’s fail again,,,

      [revival@localhost ~]$ dos2unix $HOME/bin/
      bash: dos2unix: command not found

      Then I think I will need to type out the script by own,,,,anyway,,,,thanks so much for helping until now,,,,I appreciate all your kindness

      I will tell again the result


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.