0

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.

1 Answer 1

3

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.

2
  • 1
    The full command with null termination to guard against spaces within the path is: source "$(find ~/.virtualenvs/ -maxdepth 1 -type d -print0 | fzf --read0)"/bin/activate Jun 15, 2022 at 23:44
  • Thanks, I've updated the answer to reflect your comment
    – larsks
    Jun 15, 2022 at 23:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.