179

How do I execute a bash command from Ipython/Jupyter notebook passing the value of a python variable as an argument like in this example:

py_var="foo"
!grep py_var bar.txt

(obviously I want to grep for foo and not the literal string py_var)

3
  • Followup: I want to use keyword arguments such as ffmpeg -i <inputfilename> ... but somehow the answer below doesn't work well with such a command. Do you know of an alternative solution? Commented Oct 1, 2018 at 3:24
  • @Aalok: How about the edited answer? Can you please check now. If it doesn't work, then please post the entire command you are trying to run. Commented May 6, 2019 at 4:45
  • 1
    For those looking to pass the python variable to a bash cell (magic %%bash), see this question Commented Oct 13, 2022 at 8:47

4 Answers 4

250

Simple case

Prefix your variable names with a $.

For example, say you want to copy a file file1 to a path stored in a python variable named dir_path:

dir_path = "/home/foo/bar"
!cp file1 $dir_path

General case

Wrap your variable names in {..}:

dir_path = "/home/foo/bar"
!cp file1 {dir_path}

Its behaviour is more predictable and powerful than $... E.g. if you want to concatenate another string sub_dir to your path, $ can't do that, while with {..} you can do:

!cp file1 {dir_path + sub_dir}
  • Note: Again for Bash, quotes:

    !cp file1 "{dir_path}"
    
    !cp file1 "{dir_path + sub_dir}"
    

Raw strings

For a related discussion on the use of raw strings (prefixed with r) to pass the variables, see Passing Ipython variables as string arguments to shell command

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

11 Comments

While !cp file1 $dir_path and !cp file1 {dir_path} have similar result, I found that using $ is a bit risky, because with {}, you can concatenate a path, something like !cp file1 {folder + dir_path}, whereas !cp file1 $folder + $dir_path deletes all your folder file. Be careful.
If there are spaces in the variable, don't forget to add quotes!. For example if it is thisdir_path = "/home dir/foo/bar", use quotes like this: !cp file1 "$dir_path". This adds quotes to the bash command.
Does not work among interpreters (e.g. if you do %%bash echo $dir_path instead of !echo $dir_path`)
Here is the way to do this when IPython variable is a string inserted into a shell string: stackoverflow.com/questions/35497069/…
FYI for Colab users: the {variable} notation doesn't work the same way for Google Colab notebooks. If your python variable contains spaces or anything that breaks cmd line commands, you still need to enclose it in quotes. So !cp file1 "{dir_path}". Adding values of multiple variables does work - but quotes needed around it if it may have spaces: !cp "{filename + filename}" "/content/drive/My Drive/"
|
16

You cans use this syntax too:

path = "../_data/"
filename = "titanicdata.htm"
! less {path + filename}

Comments

3

As @Catbuilts points out, $'s are problematic. To make it more explicit and not bury the key example, try the following:

afile = 'afile.txt'
!echo afile
!echo $PWD
!echo $PWD/{afile}
!echo {pwd + '/' + afile}

And you get:

afile.txt
/Users/user/Documents/adir
/Users/user/Documents/adir/{afile}
/Users/user/Documents/adir/afile.txt

5 Comments

There no simple solution to use both Python's and environment variables in one command. As a workaround, we can create a string variable as following: command = f"echo $PWD/{afile}" !{command}
For !echo {pwd+'/'+afile}, I get {pwd+/+afile}. It seems like you forgot to define a Python variable named pwd or maybe you meant to use Bash command expansion: !echo {'$(pwd)' + '/' + afile}
For !echo afile, I get afile, not afile.txt. Did you forget the dollar sign $?
@Dmitry You don't need to embed the whole command in a variable, just the environment variable: !echo {'$PWD/' + afile}
Looking at the docs, the better solution is to double up the dollar on the env var: !echo $$PWD/$afile. This makes it so it's passed along to the shell instead of being expanded by IPython.
0

Just an addition. In my case, and as shown in some of the examples in this question, my arguments were file names with spaces. Is that case I had to use a slightly different syntax: "$VAR". An example would be

touch "file with spaces.txt"
echo "this is a line" > "file with spaces.txt"
echo "this is another line" >> "file with spaces.txt"
echo "last but not least" >> "file with spaces.txt"
echo "the last line" >> "file with spaces.txt"
cat "file with spaces.txt"

# The variable with spaces such as a file or a path
ARGUMENT="file with spaces.txt"
echo $ARGUMENT

# The following might not work
cat $pwd$ARGUMENT

# But this should work
cat $pwd"$ARGUMENT"

I hope this helps. ;)

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.