Cannot source file using find, fzf, and xargs
I am trying to use fzf to select and activate different virtual environments. However, I am receiving the follow error:
xargs: source: No such file or directory
My command comprises three parts: find | fzf | xargs
(1) find locates my virtual environments,
(2) a virtual environment is selected using fzf, and
(3) xargs is used to source
the selected file.
Below is the full command:
find ~/.virtualenvs/ -maxdepth 1 -type d | fzf | xargs -I {} source {}/bin/activate
xargs: source: No such file or directory
I can directly source the file (i.e., command prompt shows entry into fzf_delete virtual environment):
brian:~$ source /home/brian/.virtualenvs/fzf_delete/bin/activate
(fzf_delete) brian:~$
I can select the virtual environment using fzf:
find ~/.virtualenvs/ -maxdepth 1 -type d | fzf
/home/brian/.virtualenvs/fzf_delete
I have also isolated the issue to xargs by removing the dependency on find and fzf:
echo "/home/brian/.virtualenvs/fzf_delete" | xargs -I {} source {}/bin/activate
xargs: source: No such file or directory
I have tried every variation of quoting, use of variables, string concatenation, command substitution, using bash -c, etc. that I can think of to no avail.
How can I get xargs to source the selected file?
PS – I am aware that null termination should be used with find, fzf, and xargs in case file names contain spaces, but that does not appear to be causing the immediate issue.
source
is a shell built-in command. You’re not going to be able to run with xargs
, because xargs
can’t make changes to your current shell. That is, even if you were to do something like ... | xargs -I {} sh -c 'source {}/bin/activate'
it wouldn’t help, because:
- Your current shell spawns xargs
- xargs spawns a new shell
- The new shell sources your file
- The new shell exits
- xargs exits
And you’re back where you started with no modifications to your environment.
On the other hand, this would work:
source "$(find ~/.virtualenvs/ -maxdepth 1 -type d -print0 | fzf --read0)"/bin/activate
Note that for the same reason you can’t use xargs
, you also can’t run the above command via a shell script. That is, if you create $HOME/bin/select-venv
with that command and make it executable, it won’t work because it will spawn in a subshell.
You can, however, create a select_venv
function or alias in your current shell.