Installing programs on a flash drive so that they can be executed in place

software installation

When reading answers to this post, I wonder if we can make the programs we often used on our computers portable (in the Windows sense), so that we can make a copy of them on our flash drive, so that we don't have to worry if we don't have access to the programs we like on other computers?

Is it possible to make such portable installations?

Best Answer

Yes, you can do that. It's more work than relying on a package manager — the main attraction of “portable” installations under Windows is not to have to fight the lack of a decent package manager.

You'll need to arrange for the programs to find their dependencies: data files, libraries, etc. Many programs support environment variables for that. Some check the directory where the binary is located, or relative directories like ../lib, for companion files

Install the software under some root directory. Create the usual category directories under that root: bin, lib, man, etc. To manage all the software, install each one independently and then use a program like Stow create a forest of symbolic links to link them to the category directories. See Keeping track of programs for an introduction to Stow. You'll thus have symbolic links like

bin/foo -> ../stow/foo-1.42/bin/foo
bin/foobar -> ../stow/foo-1.42/bin/foobar
man/man1/foo.1 -> ../../stow/foo-1.42/man/man1/foo.1
…

You'll want a script to set up environment variables. Put it at the root of your installation and use $0 to locate the script. Since a script can't influence its parent, the usual approach is to make the script produce output that can be evaluated by the calling shell. Let's call this script setup.sh.

#!/bin/sh
set -e
root=$(dirname -- "$0")
cd -- "$root"
printf "PORTABLE_ROOT='%s'\\n" "${PWD}" | sed "s/'/'\\\\''/g"
prepend () {
  eval "set -- \"\$1\" \"\$2\" \"${$1}\""
  case :$3: in
    *:$PORTABLE_ROOT/$2:*) :;; # already there (at any location)
    :: echo '$1=$PORTABLE_ROOT/$2; export $1';; # the path was empty
    *) echo '$1=$PORTABLE_ROOT/$2:$3; export $1';; # prepend
  esac
}
prepend PATH bin
prepend MANPATH man
prepend LD_LIBRARY_PATH lib
prepend PERL5LIB lib/perl
prepend PYTHONPATH lib/python
…

(Warning: untested code)

To use the portable installation from a shell, run eval "`/path/to/setup.sh`".

Related Question