16

My $PATH looks like this:

/home/torbjorr/deployed/vector/x86_64-GNU%2fLinux:/home/torbjorr/deployed/typewriter/x86_64-GNU%2fLinux:/home/torbjorr/deployed/mustudio/x86_64-GNU%2fLinux:/home/torbjorr/deployed/mathext/x86_64-GNU%2fLinux:/home/torbjorr/deployed/doxymax/x86_64-GNU%2fLinux:/home/torbjorr/deployed/c2tex/x86_64-GNU%2fLinux:/home/torbjorr/deployed/x86_64-GNU%2fLinux/wand:/home/torbjorr/deployed/x86_64-GNU%2fLinux/spellesc:/home/torbjorr/deployed/x86_64-GNU%2fLinux/projinit:/home/torbjorr/deployed/x86_64-GNU%2fLinux/herbs:/home/torbjorr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

In bash, I can without problem invoke wand located in

/home/torbjorr/deployed/x86_64-GNU%2fLinux/wand

like

$ wand
(i) Mål från "main.cpp" har registrerats
(i) Skapar katalog "__wand_targets_dbg"
(i) Kör g++ "main.cpp" -fpic -L"/home/torbjorr/deployed"  -g -Wall -std=c++11 -I"/home/torbjorr/deployed" -o "__wand_targets_dbg/cb-template

However, in bourne shell compatibility mode, wand cannot be found:

$ wand
sh: 2: wand: not found

It seems like the problem is the % sign in these paths. This sign has been added by URL encoding so the name "GNU/Linux" can be used in the directory name even though it is not a valid filename. Is it possible to get the name working in sh, or make the sh command work as bash. That is, make bash behave the same even though it was invoked with the /bin/sh command, which symlinks to bash anyway.

1 Answers1

15

That's not the Bourne shell, or bash emulating the Bourne shell, that's the Almquist shell, in your case probably the Debian Almquist shell (a Linux fork by Debian of BSDs' sh itself based on the original Almquist shell).

In the Almquist shell (the original one and the modern versions), % is used in PATH for extra features specific to ash. Quoting from the documentation:

Path Search

When locating a command, the shell first looks to see if it has a shell function by that name. Then, if PATH does not contain an entry for %builtin, it looks for a builtin command by that name. Finally, it searches each entry in PATH in turn for the command.

The value of the PATH variable should be a series of entries separated by colons. Each entry consists of a directory name, or a directory name followed by a flag beginning with a percent sign. The current directory should be indicated by an empty directory name. If no percent sign is present, then the entry causes the shell to search for the command in the specified directory. If the flag is %builtin then the list of shell builtin commands is searched. If the flag is %func then the directory is searched for a file which is read as input to the shell. This file should define a function whose name is the name of the command being searched for.

Command names containing a slash are simply executed without performing any of the above searches.

Other shells like ksh or zsh have a similar autoloading of functions mechanism, but they use a different variable ($FPATH), but you can't define which of functions or executables take precedence.

In your case, /home/torbjorr/deployed/vector/x86_64-GNU%2fLinux is interpreted as the /home/torbjorr/deployed/vector/x86_64-GNU directory with the 2fLinux flag. That flag is ignored as it is unknown.

There is no way around that. Even if ash had an escape mechanism so that this % not be treated specially, it would then not work in other shells or other things that look up $PATH like execvp().

You'll need to remove the % characters from $PATH, so rename your directory or add a symlink.

Or don't use ash for your /bin/sh. Other lightweight POSIX shell implementations that don't do that include yash and mksh.

  • Although this answer gives an explanation, it does not give a solution. Is there a compatible way of keeping %. – user877329 Apr 29 '14 at 07:07
  • @user877329, there's no real solution here. See my edit. – Stéphane Chazelas Apr 29 '14 at 07:14
  • 3
    In other words, the Debian sh violates the POSIX standard. Given that the point of having a separate sh is exactly that you should be sure not to trip over some incompatible shell extension (I guess nobody uses /bin/sh as login shell these days), I'd consider that a bug. – celtschk Apr 29 '14 at 07:47
  • 1
    @celtschk, agreed though the point of using ash for /bin/sh is more to avoid the performance penalty of using bash, so using yash or mksh (or posh if you want to exclude all extensions) is still a better option than using bash. Also, one may consider it a corner case. Nobody would normally have % in a path component. Most shells have corner cases where they're not POSIX compliant. – Stéphane Chazelas Apr 29 '14 at 09:29
  • Very nice answer, I didn't know about this "feature" of dash (and the older ash shell). It might be worth mentioning in your answer that % is also not in the POSIX portable filename character set, so conforming POSIX applications do not have to support pathnames containing a % character. – Michael Miller Apr 30 '14 at 01:43
  • @mtmiller Doesn't _nix accept everything expect '\0' and '/'. A good rule: If open(2) accepts it, so shall all other apps. – user877329 Apr 30 '14 at 07:50
  • 1
    @mtmiller, that's not how I read the meaning of the portable filename character set (PFCS). POSIX specifies programming APIs but not filesystem implementations. the PFCS is the minimum POSIX guarantees will work whatever the filesystem, whatever the current locale but is no excuse for a tool not to accept a character in a filename if it's supported by the filesystem and valid in the current locale. Note that for instance POSIX requires there be a [ command even though that character is not in the PFCS. – Stéphane Chazelas Apr 30 '14 at 11:09
  • @StephaneChazelas, I'm sure filesystem limitations and locales are the reason for the PFCS. But it does leave open the possibility that conforming libraries or applications do not have to accept characters outside of the set as part of legal pathnames, or the possibility of reserving them for different behavior. Not arguing right or wrong, just saying someone could argue that portable pathnames should not contain %. And this is a good corner case to illustrate that non-portable pathnames may not always work, and dash is not necessarily violating POSIX (open to interpretation). – Michael Miller Apr 30 '14 at 13:03