Quantcast
Channel: User Kamil Maciorowski - Super User
Viewing all articles
Browse latest Browse all 837

Answer by Kamil Maciorowski for Is there a way to sort command-line commands into namespaces on Linux?

$
0
0

First, create a suitable directory structure:

# your desired namespacemkdir -p -- "$HOME"/.namespaces/wasi-sdk# some testing namespacesmkdir -p -- "$HOME"/.namespaces/bar "$HOME"/.namespaces/baz "$HOME"/.namespaces/surprise

Populate the directories:

# your desired utilityln -s -- /usr/bin/wasi-sdk/clang "$HOME"/.namespaces/wasi-sdk/clang# some testing utilitiesln -s -- /usr/bin/date "$HOME"/.namespaces/bar/fooln -s -- /usr/bin/echo "$HOME"/.namespaces/baz/fooln -s -- /usr/bin/date "$HOME"/.namespaces/surprise/lsln -s -- /usr/bin/ls   "$HOME"/.namespaces/surprise/dateln -s -- /usr/bin/ls   "$HOME"/.namespaces/surprise/foo

Create more symlinks:

( cd -- "$HOME"/.namespaces \&& find . ! -type d -path './*/*' -exec sh -c '   for f do      n="$(printf "%s\\n" "$f" | sed "s|/|.|g; s|^\\.\\.|./|")"      ln -s -- "$f" "$n"   done' find-sh {} +)

Do not worry if you don't understand the above code; in the future you may as well create and manage symlinks manually. This is how the directory structure looks now:

$ ( cd -- "$HOME"/.namespaces && tree ).├── bar│  └── foo -> /usr/bin/date├── bar.foo -> ./bar/foo├── baz│  └── foo -> /usr/bin/echo├── baz.foo -> ./baz/foo├── surprise│  ├── date -> /usr/bin/ls│  ├── foo -> /usr/bin/ls│  └── ls -> /usr/bin/date├── surprise.date -> ./surprise/date├── surprise.foo -> ./surprise/foo├── surprise.ls -> ./surprise/ls├── wasi-sdk│  └── clang -> /usr/bin/wasi-sdk/clang└── wasi-sdk.clang -> ./wasi-sdk/clang5 directories, 12 files

So in the "namespace" directories there are symlinks to real utilities. Additionally in the "main" directory there are symlinks (named namespace.name) to those symlinks.

Add the "main" directory to your $PATH:

PATH="$HOME/.namespaces:$PATH"

Now bar.foo is date and baz.foo is echo (try baz.foo Hello World). More importantly wasi-sdk.clang should work for you.

To be able to use use wasi-sdk as you wish, define a function that will manipulate your $PATH:

use () {   PATH="$(      dir="$HOME"/.namespaces      oldpath="$PATH"      newpath="$dir"      for namespace do         entry="$dir/$namespace"         if [ -d "$entry" ]; then            newpath="$newpath:$entry"         else            printf 'Namespace %s not found.\n'"$namespace" >&2         fi      done      while [ -n "$oldpath" ]; do         IFS=: read -r entry oldpath <<EOF$oldpathEOF         case "$entry" in"$dir"/* | "$dir")               entry=''               ;;            *)               entry=":$entry"               ;;         esac         newpath="$newpath$entry"      done   printf '%s'"$newpath"   )"}

Now you can run use wasi-sdk and it will do what you want. You can run use surprise to "swap" date and ls (note this ls will fail if there is an alias like alias ls='ls --color=auto'), and to make foo behave like ls. Better, you can run use bar surprise to "swap" date and ls (like in surprise), and to make foo behave like date (like in bar, overriding surprise).

In general use namespace1 namespace2 namespace3 ... allows you to use multiple namespaces (namespace1 has the highest priority). The function is quite dumb (e.g. it will not deduplicate the list, it will happily accept ../../..).

To stop using namespaces this way, run use without arguments. Note it will still add the "main" directory to the path, even if it wasn't there before. This is deliberate, so you can choose not to change your $PATH account-wide and "activate" the support for this namespace.name syntax only on demand by invoking use (with or without arguments) for the first time.

Note that in general a program may adjust its behavior according to the name used to call it (example). Running such a program via a symlink named namespace.name may break things.


Viewing all articles
Browse latest Browse all 837

Trending Articles