Prozent in der Umgebungsvariablen $ PATH

16

Mein $ PATH sieht so aus:

/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 der bash kann ich problemlos den in befindlichen Zauberstab aufrufen

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

mögen

$ 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

Im Bourneshell-Kompatibilitätsmodus kann der Zauberstab jedoch nicht gefunden werden:

$ wand
sh: 2: wand: not found

Das Problem scheint das% -Zeichen in diesen Pfaden zu sein. Dieses Zeichen wurde durch URL-Codierung hinzugefügt, sodass der Name "GNU / Linux" im Verzeichnisnamen verwendet werden kann, obwohl es sich nicht um einen gültigen Dateinamen handelt. Ist es möglich, den Namen in sh zum Laufen zu bringen, oder den Befehl sh als bash auszuführen? Dies bedeutet, dass Bash sich genauso verhält, obwohl es mit dem Befehl / bin / sh aufgerufen wurde, der sowieso auf Bash verweist.

user877329
quelle
Gute Frage. Es scheint, dass das Zeichen '%' in $ PATH from nicht richtig funktioniert sh(es ist in bashund zshobwohl in Ordnung). Das direkte Aufrufen der ausführbaren Datei funktioniert sh. wirklich seltsam.
Rmano
Was passiert, wenn Sie 2 %% verwenden?
mikeserv
Oder dem% entkommen?
MDPC

Antworten:

15

Das ist nicht die Bourne-Shell oder die bashEmulation der Bourne-Shell, das ist die Almquist-Shell, in Ihrem Fall wahrscheinlich die Debian-Almquist-Shell (ein Linux-Fork von Debian, der auf der ursprünglichen Almquist-Shell basiert).

In der Almquist-Shell (die ursprüngliche und die moderne Version) %wird in PATHfür zusätzliche Funktionen verwendet, die spezifisch sind ash. Zitat aus der Dokumentation:

Pfadsuche

Beim Auffinden eines Befehls prüft die Shell zunächst, ob sie eine Shell-Funktion mit diesem Namen hat. Wenn PATH dann keinen Eintrag für enthält %builtin, sucht es nach einem eingebauten Befehl mit diesem Namen. Schließlich durchsucht es jeden Eintrag in PATH nach dem Befehl.

Der Wert der Variablen PATH sollte eine Reihe von Einträgen sein, die durch Doppelpunkte getrennt sind. Jeder Eintrag besteht aus einem Verzeichnisnamen oder einem Verzeichnisnamen, gefolgt von einem Flag, das mit einem Prozentzeichen beginnt. Das aktuelle Verzeichnis sollte durch einen leeren Verzeichnisnamen gekennzeichnet sein. Wenn kein Prozentzeichen vorhanden ist, führt der Eintrag dazu, dass die Shell im angegebenen Verzeichnis nach dem Befehl sucht. Wenn das Flag ist, %builtin wird die Liste der in die Shell eingebauten Befehle durchsucht. Wenn das Flag ist, %func wird das Verzeichnis nach einer Datei durchsucht, die als Eingabe in die Shell gelesen wird. Diese Datei sollte eine Funktion definieren, deren Name der Name des gesuchten Befehls ist.

Befehlsnamen, die einen Schrägstrich enthalten, werden einfach ausgeführt, ohne dass eine der oben genannten Suchvorgänge ausgeführt wird.

Andere Shells mögen kshoder zsheinen ähnlichen automatischen Laden von Funktionen Mechanismus haben, aber sie verwenden eine andere Variable ( $FPATH), aber Sie können nicht , welche Funktionen oder ausführbare Dateien haben Vorrang definieren.

In Ihrem Fall /home/torbjorr/deployed/vector/x86_64-GNU%2fLinuxwird als /home/torbjorr/deployed/vector/x86_64-GNUVerzeichnis mit dem 2fLinuxFlag interpretiert . Dieses Flag wird ignoriert, da es unbekannt ist.

Daran führt kein Weg vorbei. Auch wenn Asche hat so einen Flucht - Mechanismus , dass dies %nicht speziell behandelt werden, wäre es dann nicht die Arbeit in anderen Schalen oder anderen Dingen , die sehen $PATHwie execvp().

Sie müssen die %Zeichen aus entfernen $PATH, also benennen Sie Ihr Verzeichnis um oder fügen Sie einen Symlink hinzu.

Oder nicht ashfür deine verwenden /bin/sh. Andere einfache POSIX-Shell-Implementierungen, die dies nicht tun, umfassen yashund mksh.

Stéphane Chazelas
quelle
Obwohl diese Antwort eine Erklärung gibt, gibt sie keine Lösung. Gibt es eine kompatible Möglichkeit,% zu behalten?
user877329
@ user877329, hier gibt es keine echte Lösung. Siehe meine Bearbeitung.
Stéphane Chazelas
3
Mit anderen Worten, das Debian shverstößt gegen den POSIX-Standard. Angesichts der Tatsache, dass der Sinn einer separaten shShell genau darin besteht, dass Sie sicher sein sollten, nicht über eine inkompatible Shell-Erweiterung zu stolpern (ich vermute, dass derzeit niemand sie /bin/shals Anmeldeshell verwendet ), würde ich das als Fehler betrachten.
Celtschk
1
@celtschk, obwohl der Sinn der Verwendung ashvon / bin / sh mehr darin besteht, den Leistungsverlust durch die Verwendung zu vermeiden. Daher ist die bashVerwendung von yashoder mksh(oder poshwenn Sie alle Erweiterungen ausschließen möchten) immer noch eine bessere Option als die Verwendung von bash. Man kann es auch als Eckfall ansehen. Normalerweise hätte niemand %eine Pfadkomponente. Die meisten Shells haben Eckgehäuse, in denen sie nicht POSIX-konform sind.
Stéphane Chazelas
1
@mtmiller, so lese ich nicht die Bedeutung des portablen Dateinamen-Zeichensatzes (PFCS). POSIX gibt Programmierschnittstellen an, jedoch keine Dateisystemimplementierungen. Das PFCS ist das Minimum, von dem POSIX garantiert, dass es unabhängig vom Dateisystem und der aktuellen Ländereinstellung funktioniert. Es ist jedoch keine Entschuldigung dafür, dass ein Tool Zeichen in einem Dateinamen nicht akzeptiert, wenn dies vom Dateisystem unterstützt wird und in der aktuellen Ländereinstellung gültig ist. Beachten Sie, dass beispielsweise für POSIX ein [Befehl erforderlich ist, obwohl sich dieses Zeichen nicht im PFCS befindet.
Stéphane Chazelas