8
$\begingroup$

I want to search for a value in the VASP OUTCAR file i.e the format of the line should be

 Volume of Typ   1:     98.5 %

What command line should I type in OUTCAR to go for a specific line or word?

$\endgroup$
7
  • 2
    $\begingroup$ Maybe you are looking for the command grep? phoenixnap.com/kb/grep-command-linux-unix-examples $\endgroup$
    – S R Maiti
    Mar 22, 2021 at 12:04
  • 2
    $\begingroup$ Yes, grep is the way to go. For your case that would be: grep 'Volume of' OUTCAR $\endgroup$
    – Fabian
    Mar 22, 2021 at 12:30
  • 11
    $\begingroup$ In the future, I would search StackOverflow (or for this particular example, Unix/Linux SE) first for questions that are about general programming (or general tools in Linux). Answer on SO, Answer on Unix SE $\endgroup$
    – Tyberius
    Mar 22, 2021 at 14:28
  • 1
    $\begingroup$ I’m voting to close this question because this question is about a basic operation in Linux environment and has nothing to do with Matter Modeling. $\endgroup$ Mar 24, 2021 at 14:15
  • 1
    $\begingroup$ As I see it, the most difficult part is all about asking the right question. The OP's problem is to dig out a specific portion of the VASP output. The right place to ask that question is definitely MMSE. Incidentally it can be argued that the solution belong to someother SE $\endgroup$
    – Thomas
    Mar 24, 2021 at 16:32

4 Answers 4

15
$\begingroup$

The OUTCAR is a text file. Therefore, you can use the grep command to grab what you want to search for.

  • Print the current line:

    grep  "key_information_string" OUTCAR
    
  • Print more lines below the current line:

    grep  "key_information_string" OUTCAR -A n
    
  • Print more lines above the current line:

    grep  "key_information_string" OUTCAR -B n
    

Here $n$ represents the number of lines you want to print, such as 5.

$\endgroup$
9
  • 1
    $\begingroup$ +1. I've given more examples of using grep here: mattermodeling.stackexchange.com/a/2416/5 $\endgroup$ Mar 22, 2021 at 16:54
  • $\begingroup$ I think it's worth explaining that n is to be substituted with the number of lines. $\endgroup$
    – Ruslan
    Mar 22, 2021 at 21:13
  • $\begingroup$ @Ruslan I have added that. $\endgroup$
    – Jack
    Mar 23, 2021 at 0:53
  • 1
    $\begingroup$ At you service, @nick012000. (Someone appears to be having a bad day.) $\endgroup$ Mar 23, 2021 at 5:04
  • 2
    $\begingroup$ There's a small miswording in the description of the -A and -B flags. The -A flag shows lines after the match, and -B shows lines before the match. $\endgroup$
    – Robobunny
    Mar 24, 2021 at 14:15
14
$\begingroup$

Use rg

If you have a significant size file or file(s) to search, do yourself a favor and choose one of the many significantly faster alternatives to grep, the de facto fastest being ripgrep.

Specific values

# literal string
rg <options> 'Volume of Typ   1:     98.5 %'     path/to/file/or/directory
# any value for the key
rg <options> 'Volume of Typ   1:'                path/to/file/or/directory
# any numeric value
rg <options> 'Volume of Typ   1:\s*\d+\.?\d*'    path/to/file/or/directory
# any numeric percentage
rg <options> 'Volume of Typ   1:\s*\d+\.?\d*\s%' path/to/file/or/directory

Where <options> are any additional parameters you want to pass (may be omitted).
The path argument may be omitted as well, it defaults to the current working directory.
Obviously, you could make the search parameter for the key a pattern too.

N.B. The syntax is the same for grep (or ag, or the like).

Selection

If you wanted to select the values only (as in strip the key and unit / suffix), sed is an option:

cat path/to/file | sed -en 's!^Volume of Typ\s*1:\s*\([0-9]*\.[0-9]*\).*$!\1!gp'

At this point, you've got a list of line-terminated, matched values on your screen.
Neato, no more noise!

Next

Other than looking at the output on screen, you could:

  • store it in another file <previous_command> > path/to/values.csv
  • pipe it to the next command (e.g. to visualize the values):
    <previous_command> | awk '{print NR " " $0}' | gnuplot -p -e "plot '<cat'"
    (Exercise left to the avid reader: The extraction of the Typ n type number to plot on the x-axis, instead of the running index NR.)

Narrower conditions are obviously possible.

Tips

  • Single quoted ' strings make regexes in the shell significantly easier to type.
  • Use a better delimiter for sed than the often cited /, ! for instance.

References

Bonus: sed breakdown

cat path/to/file | sed -en 's!^Volume of Typ\s*1:\s*\([0-9]*\.[0-9]*\).*$!\1!gp'
  • cat1 reads the file from disk and prints its contents to stdout
  • | is a pipe
  • sed is a stream editor:
    • the -e flag isn't strictly necessary, it's just there to allow for possibly multiple "script" inputs at once
    • -n suppresses output (get rid of non-matching lines)
    • the script argument decodes as s!<search_pattern>!<replacement>!<flags>
      • wherein <search_pattern>
        • ^ beginning of the line
        • Volume of Typ literal string to be matched
        • \s* any number of whitespaces
        • : literal string to be matched
        • \s* any number of whitespaces
        • (...) group that may be referenced (no effect on matching)
        • [0-9]* any number of digits (character class with a * quantifier)
        • \. an escaped, literal period (. has a logical meaning in regular expressions)
      • wherein <replacement> is \1, a backreference to the group (...) above
      • wherein the <flags> are:
        • g apply globally (you want more than one match)
        • p print matches to stdout (we had negated all output with -n earlier to get rid of non-matching lines)

1 For the sake of completeness: cat's actual purpose is text (or file) concatenation and it takes any number of arguments. Most of its invocations in its lifetime have certainly been with one argument to read a file.

$\endgroup$
3
$\begingroup$

To search for all the strings in all of the files in current folder you would use simply:

grep string *

Or in subfolder:

grep string subfolder/*

Unfortunately recursion is not possible so you can only search one folder at the time.

$\endgroup$
3
  • $\begingroup$ Welcome to the site! Can you elaborate on what this adds that isn't included in the existing answers? Also, most newer versions of grep allow a recursive search by using the -r flag. $\endgroup$
    – Tyberius
    Mar 24, 2021 at 14:43
  • $\begingroup$ @Tyberius Answer from @Jack uses grep so that it targets a speciffic file, but you can target multiple files like I did here. I did not know about the recursion!? How can this be done? Can you give me an excakmple here in the comments? $\endgroup$
    – 71GA
    Mar 24, 2021 at 18:35
  • 1
    $\begingroup$ If you do grep -R "some string" ./, it will search for "some string" in every file in every subdirectory of ./ . Using -R, rather than -r, even allows it to search through symbolic links. This is at least the case for GNU grep version 2.20. $\endgroup$
    – Tyberius
    Mar 26, 2021 at 18:36
3
$\begingroup$

If you open with vim, you can find it by following command line.

vim OUTCAR and input '?Volume of Type' or '/Volume of Type', press n or N to find previous one next one with string 'Volume of Type'.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .