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)
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
Note: If using Bash, keep in mind that some strings need to be quoted:
!cp file1 "$dir_path"
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}"
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
!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.dir_path = "/home dir/foo/bar", use quotes like this: !cp file1 "$dir_path". This adds quotes to the bash command.%%bash echo $dir_path instead of !echo $dir_path`){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/"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
command = f"echo $PWD/{afile}" !{command}!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}!echo afile, I get afile, not afile.txt. Did you forget the dollar sign $?!echo {'$PWD/' + afile}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. ;)
ffmpeg -i <inputfilename> ...but somehow the answer below doesn't work well with such a command. Do you know of an alternative solution?%%bash), see this question