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.

Asked By: user2514157

||

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:

  1. Your current shell spawns xargs
  2. xargs spawns a new shell
  3. The new shell sources your file
  4. The new shell exits
  5. 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.

Answered By: larsks
Categories: Answers Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.