Führen Sie als .test statt ./test aus

26

Angenommen, ich befinde mich im selben Ordner wie eine ausführbare Datei, dann müsste ich Folgendes eingeben, um sie auszuführen:

./file

Ich würde lieber nicht tippen müssen /, weil /es für mich schwierig ist zu tippen.

Gibt es eine einfachere Möglichkeit, eine Datei auszuführen? Idealerweise nur eine einfache Syntax wie:

.file

oder etwas anderes, aber einfacher, als das /Zeichen dort einfügen zu müssen.

Vielleicht gibt es eine Möglichkeit, etwas in das /binVerzeichnis einzufügen oder einen Alias ​​für den Interpreter zu erstellen, damit ich Folgendes verwenden kann:

p file
IMSoP
quelle
9
Vielleicht mit xmodmap / mit einem anderen Schlüssel tauschen? Zumindest ist es einfacher zu tippen
Guy
26
Als Randbemerkung, /wird verwendet , ausführlich in Unix, weitgehend als Verzeichnistrenner. Sie sind wahrscheinlich besser dran, einen einfacheren Weg zu finden, um es zu tippen.
chrylis -on strike-
7
@ RossPresser Diese Frage macht da sehr wenig Sinn. und ./ am Anfang der Datei stehen zwei völlig unterschiedliche Bedeutungen, die jeder Anfänger aus technischen Gründen kennen sollte. /ist für die große Mehrheit der Benutzer nicht schwer zu tippen, und wenn das OP eine Verletzung aufweist, die dies verhindert, sollten sie alternative Tastaturlayouts in Betracht ziehen, da sie es auf keinen Fall vermeiden können, sich /vollständig im Terminal aufzuhalten.
JFA
1
@JFA Die Mehrheit der in Kontinentaleuropa und in Südamerika verwendeten Tastaturlayouts verwendet /Shift-7, dessen Eingabe selbst ohne Verletzung vergleichsweise schwierig ist.
Nitro2k01
6
Bearbeiten Geschichte: „ Warum kann Network Interface einfach angewiesen werden, alle Internet - Anfragen über eine Remote - Host zu machen via ssh auf Port 22 “ ಠ_ಠ
Derek朕會功夫

Antworten:

35

Es kann "riskant" sein, aber Sie könnten nur haben. in deinem PFAD.

Wie in anderen gesagt wurde, kann dies gefährlich sein, stellen Sie also immer sicher. ist am Ende des PFADS und nicht am Anfang.

HaloJones
quelle
1
Sehen Sie nicht wirklich, wie "riskant" das ist: Mein Weg war lange vor Linux so, und es hat nie das geringste Problem verursacht.
Jamesqf
21
@jamesqf Es ist riskant, da Sie cd, wenn Sie in ein Verzeichnis wechseln , das von der Welt beschreibbar ist, und versuchen, einen Befehl zu verwenden, der sich nicht in Ihrem Pfad befindet, möglicherweise eine (möglicherweise böswillige) ausführbare Datei mit demselben Namen ausführen, die jemand in diesen Pfad geschrieben hat. Dies ist viel schlimmer, wenn Sie .am Anfang Ihres Weges setzen. In diesem Fall würde eine aufgerufene böswillige ausführbare Datei lsausgeführt, wenn Sie versuchen, lsdieses Verzeichnis aufzurufen .
Bytesized
2
Bitte vermeiden Sie dies aus den oben genannten Gründen. Der pBefehl wäre besser.
Guido
11
@jamesqf Wenn es "dein" System ist und nur du es benutzt, ist es nicht so schlimm. Das Problem tritt auf einem Mehrbenutzersystem auf (und hat im Laufe der Jahre so manche Unix-Administratoren in den Schatten gestellt). Mit einem .frühen PATHZeitpunkt muss ein böswilliger Benutzer nur noch einen falschen lsBefehl in seinem Verzeichnis ablegen und den Administrator dazu verleiten, "auf etwas Seltsames zu schauen", und er hat Root-Zugriff.
TripeHound
1
Gute Lösung, auch wenn es nicht funktioniert, wenn die Datei zufällig benannt wird test, wie im Titel der Frage (da testeine Shell eingebaut ist und wahrscheinlich auch irgendwo in Ihrer $PATHbereits vorhanden ist).
Yellowantphil
71

.wird sich automatisch vervollständigen./ (tippen .und drücken Tab), zumindest in modernen Bash-Shells, sodass Sie keine komplexe oder unsichere PATHLösung (wie das Ändern) verwenden müssen.

Wenn es nicht automatisch vervollständigt wird, müssen Sie möglicherweise das Paket "bash-completion" installieren.

l0b0
quelle
Bist du sicher? .Es gibt mehrere Vervollständigungskandidaten: .(aktuelles Verzeichnis), ..(übergeordnetes Verzeichnis), den .Befehl (für den Bash ein nicht standardmäßiger Alias ​​angegeben wird source) und alle vorhandenen Punktdateien. Vielleicht bash-completionignoriert das Paket dies; Ich finde es furchtbar ärgerlich (z. B. macht es unmöglich, Verzeichnisnamen in einer makeBefehlszeile mit Tabulatoren zu vervollständigen , und es ist im Allgemeinen schrecklich, wenn Makefiles voller impliziter Regeln vorhanden sind), sodass ich sie immer lösche.
R ..
3
Ich habe es versucht und ja, es wird auf diese Weise automatisch vervollständigt. In fast allen Fällen ist es das, was sich ein normaler Benutzer wünscht: Ich glaube, ich habe noch nie eine Punktdatei gesehen, die ausführbar sein sollte. Etwas in einem Unterverzeichnis auszuführen, ist weitaus üblicher als etwas in einem übergeordneten Verzeichnis eine verdammt gute Arbeit, um makeZiele zu finden.
l0b0
Mit Bash 3.2 wird es nicht automatisch vervollständigt. Könnte dies neu in Bash 4 sein?
Calimo
2
@Calimo Neu in neueren Versionen von Bash-Completion. Es ist alles andere als eine grundlegende Veränderung.
08.02.17 Uhr,
42

oder .. vielleicht dem Interpreter einen Alias ​​in der bashrc-Datei geben und dann einfach

   p  file

Es ist möglich, eine solche Funktion zu schreiben:

p() {
 ./"$@"
}

in deinem ~/.bashrc. Dann können Sie p app argumentsstattdessen laufen ./app arguments. Diese Lösung funktioniert für ausführbare Dateien aller Art, einschließlich Skripts und Binärdateien.

"$@"dehnt sich in geeigneter Weise zitierte Liste der Argumente an die Funktion übergeben (alle Sonderzeichen aus glob oder variable Expansion zu bewahren), und als @ Scott wies darauf hin, bashklug genug , um prepend ist ./auf der ersten von ihnen, den Rest zu erhalten.

aitap
quelle
Obwohl es weniger allgemein ist, strace -f p appAnwendungen unter einem anderen Befehl auszuführen, möchten Sie Systemaufrufe sehen oder $(which time) p appsehen, wie lange es dauert. pDa ein ausführbares Skript in diesen beiden Beispielen besser funktionieren würde, habe ich es mir ausgedacht. Weder Lösung konnte mit der Arbeit ldd p app, wenn auch ldd auch unterscheidet einen vollständigen Pfad in erfordern, vielleicht aus Gründen wie diese.
Sourcejedi
Ja, das Ersetzen p app argsdurch ./app argsin einer Weise, die für niemanden unsichtbar ist, würde die Eingabe einer Pipeline-Shell durch eine Art Präprozessor erfordern und jede
Menge
1
Sollte es in diesem Fall keine Anführungszeichen geben $@? Andernfalls wird nur ein großes Argument an das Programm übergeben.
Kroltan
7
@Kroltan No. $@ist ein Array. Wenn innerhalb von erweitert ", wird jeder Parameter zu einem separaten Wort erweitert. $*verhält sich wie du denkst.
8bittree
3
Ich glaube, Sie haben das unnötig komplex gemacht, und das p() { ./"$@"; }ist alles, was Sie brauchen.
Scott
11

Sie können dies tun ., $PATHindem Sie z. B. PATH=$PATH:.zu Ihrem hinzufügen /etc/profile. Auf diese Weise können Sie es filenur durch Schreiben ausführen file, es sei denn, es befindet sich in einem anderen Ordner in Ihrem Pfad (z /usr/bin/. B. ). Beachten Sie, dass dies im Allgemeinen keine gute Idee ist.

Warum es so schlimm ist: Angenommen, Sie befinden sich in einer Situation, in der Sie dem Inhalt eines Verzeichnisses nicht vollständig vertrauen - Sie haben es von einem zweifelhaften Ort heruntergeladen und möchten es untersuchen, bevor Sie es ausführen, oder Sie sind ein Sysadmin, der einigen hilft Sie möchten das Verzeichnis auflisten, also versuchen Sie, ls einzugeben, aber hoppla, Sie machen einen Tippfehler und geben stattdessen sl ein. Der Autor dieses schädlichen Verzeichnisses hat dies vorausgesehen und ein Shell-Skript namens "sl" eingefügt, in dem "rm -rf --no-preserve-root /" (oder etwas Bösartigeres wie die Installation eines Rootkits) ausgeführt wird.

(Danke @Muzer für die Erklärung)

phk
quelle
13
Obwohl ich voll und ganz zustimme, wird es wahrscheinlich genau erklären, warum dies keine gute Idee ist.
Ymbirtt
16
Warum es so schlimm ist: Angenommen, Sie befinden sich in einer Situation, in der Sie dem Inhalt eines Verzeichnisses nicht vollständig vertrauen - Sie haben es von einem zweifelhaften Ort heruntergeladen und möchten es untersuchen, bevor Sie es ausführen, oder Sie sind ein Sysadmin, der einigen hilft Sie möchten das Verzeichnis auflisten, also versuchen Sie, ls einzugeben, aber hoppla, Sie machen einen Tippfehler und geben stattdessen sl ein. Der Autor dieses schädlichen Verzeichnisses hat dies vorausgesehen und ein Shell-Skript namens "sl" eingefügt, in dem "rm -rf --no-preserve-root /" (oder etwas Bösartigeres wie die Installation eines Rootkits) ausgeführt wird.
Muzer
2
Es lohnt sich zu erklären, dass der Angreifer, wenn sich das aktuelle Verzeichnis am Anfang von $ PATH befindet, stattdessen ls oder andere häufig verwendete Befehle außer Kraft setzen kann
Délisson Junio,
@ Muzer Huuuge Alufolie Hüte hier.
Sombrero Chicken
4
@GillBates Dies ist die Art von Dingen, die Sie als Systemadministrator beachten müssen, wenn Sie mit tatsächlichen und potenziell böswilligen Benutzern umgehen müssen, oder wenn Sie verdächtige Archive analysieren, um ihren Lebensunterhalt zu verdienen. Wenn beides nicht zutrifft, stimme ich Ihnen zu. Ich glaube immer noch nicht, dass es eine gute Angewohnheit ist, sich darauf einzulassen, denn Sie wissen nie, wann sich Ihre Umstände ändern werden, und Sie werden sich endlos dafür verfluchen, dass Sie sich darauf vorbereitet haben, sich auf unsicheres Verhalten zu verlassen. )
Muzer
10

Sie können beispielsweise den Dolmetscher anrufen

bash test

In diesem Fall wird das Skript auch dann ausgeführt, wenn es weder eine Shebang-Zeile (z. B. #!/bin/bash) noch ein ausführbares Bit enthält. Sie müssen den richtigen Interpreter kennen, um es auch ausführen zu können. Sie können die shebang-Zeile der Datei zuerst lesen, um sicherzustellen, dass Sie den richtigen Interpreter aufrufen, zum Beispiel, wenn die shebang-Zeile lautet

#!/usr/bin/env python3

du würdest anrufen

python3 test
Zanna
quelle
7
Interpreter interpretieren nur Code, sie werden keine Binärdateien ausführen
Mc Kernel
Diese Antwort ist etwas logisch, da dem Interpreter möglicherweise ein Alias ​​in der bashrc-Datei zugewiesen werden kann.
5
@ McKernel guter Punkt, es funktioniert nur, wenn es einen Interpreter gibt, nicht für kompilierte ausführbare Dateien
Zanna
2
Es gibt einen Interpreter für kompilierte ausführbare Dateien:/lib/ld.so
Dmitry Kudriavtsev
7

Soweit ich weiß, gibt es keine Möglichkeit, dies zu erreichen, es sei denn, Sie fügen die Datei in den ENV-Pfad ein, und Sie könnten es einfach ausführen, indem Sie Folgendes eingeben: file

.filefunktioniert nicht, da dies ein anderer Dateiname ist. Es ist eine Datei namens .fileund nicht ./file.

Ich habe das Gefühl, dass es schwierig sein kann, Schrägstriche für Sie zu schreiben, weil das Layout nicht englisch ist, vielleicht? In diesem Fall passiert es mir auch, also tausche ich mein Tastaturlayout häufig durch Drücken von Alt + Shift in Windows in Englisch aus (ich verwende Linux von ssh aus).

Mc Kernel
quelle
7

Die Leute haben vorgeschlagen , das Hinzufügen .zu PATH, was gefährlich ist , weil es ein Risiko darstellt, dass Sie versehentlich ein bösartiges Programm gepflanzt in einer Welt beschreibbaren Verzeichnis ausgeführt werden. Aber, wenn Sie in ein paar Verzeichnisse ausführbare Programme, die Sie besitzen und beschreibbar sind nur von Ihnen, dann ist es sicher (ziemlich sicher?) Stellen diejenigen Direktor (en) in PATH, indem Sie eine Zeile wie

PATH=$PATH:~/dev/myprog1:~/dev/myprog2

zu Ihrer ~/.bashrcDatei. Dies bedeutet natürlich, dass Sie ein Programm von einem dieser Verzeichnisse aus von einer beliebigen Stelle im Dateisystem ausführen können. Zum Beispiel könnten Sie cd /etcund eingeben foo, und es würde laufen ~/dev/myprog1/foo. Dies hat den kleinen Nachteil, dass Sie nicht in mehr als einem der Verzeichnisse gleichnamige Programme haben können. Insbesondere wenn Sie Programme haben, die foo in beiden ~/dev/myprog1und aufgerufen werden ~/dev/myprog2, können Sie das zweite Programm nur ausführen, indem Sie einen Pfad angeben. Ebenso, wenn Sie eine haben ~/dev/myprog1/cat- aber warum würden Sie wollen?


Ein anderer Ansatz, wenn Sie nur wenige Programme haben, mit denen Sie dies tun, besteht darin, Aliase für diese zu definieren:

alias gizmo='./gizmo'
alias gonzo='./gonzo'

Oder Sie können die Aliase anrufen .gizmound .gonzo wenn Sie das intuitiver finden.

Dies birgt .in gewissem Maße das gleiche Sicherheitsrisiko, das Sie auch in Ihrem Computer haben PATH. Wenn ein böswilliger Benutzer Ihre lesen kann .bashrcund Ihre Aliase sieht, dann könnte er Malware genannt gesetzt gizmound gonzoin zufälligen Verzeichnissen , in der Hoffnung , dass Sie es laufen werden. Es ist besser, dafür absolute Pfadnamen zu verwenden:

alias gizmo='~/dev/myprog1/gizmo'
alias gonzo='~/dev/myprog2/gonzo'

Übrigens sollten Sie die Benennung einer ausführbaren Datei vermeiden test, da dies ein in die Shell integrierter Befehl ist, und Sie können ein Programm mit diesem Namen nur ausführen, indem Sie einen Pfad oder einen anderen Trick angeben.

G-Man sagt, "Monica wiedereinsetzen"
quelle
Alternativ können Sie ein Rezept erstellen (wenn Sie Makefiles verwenden) und tun make gizmooder make gonzo.
Ihato
Es tut mir leid, aber ich bin nicht sicher, ob ich verstehe, wie das mit der Frage oder meiner Antwort zusammenhängt. Schlagen Sie vor, dass das OP Makefilein jedem Verzeichnis ein erstellt, sodass die Aktionen zum make gizmoBeenden ausgeführt werden gizmo ? (1) Dies scheint eine umständliche Methode zu sein, um das Gleiche zu tun wie die pin der Frage vorgeschlagene Funktion, die ursprünglich von aitap implementiert und von Scott verfeinert wurde. (2) Können Sie auf diese Weise Argumente übergeben? ISTM, make gizmo arg1 arg2das äquivalent zu ist make gizmo; make arg1; make arg2.
G-Man sagt, dass Monica
1
(1) Vielleicht ist meine Annahme falsch, aber es ist mir nicht klar, dass OP es vermeiden möchte, ./in jedem Verzeichnis etwas zu benutzen . Meiner Meinung nach entwickelt er etwas und muss das produzierte Programm nur ./fileoft ausführen . Ich kann wirklich nicht denken Sie an jedem anderen Szenario , in dem man häufig benötigen würde eine lokale Datei ausführen und wenn er es nicht läuft häufig würde er sich nicht die Mühe , die Frage zu stellen (er sagte schwierig nicht unmöglich ) (2) nicht wirklich , aber Sie können die Argumente im Rezept übergeben.
Ihato
(1) Nun, ich denke, wir können zustimmen, dass die Motivation des OP und der Umfang seiner Frage unklar sind. (2) Danke für den Link.
G-Man sagt, dass Monica
3

Um die Antwort von Zanna zu Interpreten zu erweitern (Entschuldigung, kein Mitarbeiter für einen Kommentar): Ein "Interpreter" für native ausführbare Dateien (auch als binäre ELF-Dateien bezeichnet) ist der dynamische Loader ( ld.so), versteht jedoch in der Regel nicht die gewünschte Syntax:

$ /usr/lib/ld-linux-x86-64.so.2 program
program: error while loading shared libraries: program: cannot open shared object file
$ /usr/lib/ld-linux-x86-64.so.2 ./program
<program is launched>

(Auch wenn Sie nicht ld.soauf Ihren Pfad verlinken , müssen Sie noch /s schreiben. )

bacondropped
quelle
Das ist Linux-spezifisch, oder? Könnten Sie das bitte näher erläutern, warum das so ist? Ich dachte, der (Linux-) Kernel würde das Parsing durchführen und entscheiden, ob und wie eine Binärdatei ausgeführt werden binfmt_miscsoll.
6.
2
@phk Die Datei ist Linux-spezifisch, das Konzept eines dynamischen Linkers / Loaders jedoch nicht. Zum Beispiel hat FreeBSD ein eigenes /libexec/ld-elf.so.1. Unter Linux ist es nicht so einfach wie "Entscheiden, wie eine Binärdatei ausgeführt werden soll": binfmt_miscErkennt das Format der Datei anhand von magischen Zahlen (ELF, Shebang-Skript, CIL). Danach wird der binfmt_elfHandler aufgerufen. Es analysiert ELF-Header und -Abschnitte. .interpAbschnitt enthält Pfad des dynamischen Laders; Dieser Loader wird vom Kernel gestartet, führt Umzüge durch und springt zu _start. Unter FreeBSD gibt es keine binfmt, aber das Prinzip ist +/- ähnlich.
bacondropped
1
@phk, warum dies funktioniert - ld.sohat keine .interpstatische Verknüpfung und ist statisch verknüpft. Dies bedeutet, dass kein anderer dynamischer Linker / Loader erforderlich ist, um die externen Symbole aufzulösen und die Verschiebung zu berechnen.
bacondropped
ISTR Solaris hat auch etwas Ähnliches.
G-Man sagt, dass Monica
3

Wenn wir anfangen dürfen, Dinge zu konfigurieren

mkdir -p ~/.local/bin
cat > ~/.local/bin/x << 'EOF'
#!/bin/sh
N="$1"
shift
exec "./$N" "$@"
EOF
chmod a+x ~/.local/bin/x

In den meisten modernen Distributionen ist ~ / .local / bin bereits in $ PATH enthalten (fügen Sie dies export PATH="$HOME/.local/bin:$PATH"zu Ihren hinzu , ~/.profilewenn dies bei Ihnen nicht der Fall ist). Dann kannst du x filemit rennen ./file.

Versuchen Sie nicht, einen .Befehl zu definieren . Der Befehl wird . scriptbereits scriptin der aktuellen Shell ausgeführt. Dadurch können scriptUmgebungsvariablen für die aktuelle Shell definiert werden.

sourcejedi
quelle
3
Ich denke, dass es hier einen guten Vorschlag gibt, aber es gibt keine Erklärung dafür, was dies alles bewirkt. Ich könnte es herausfinden, aber ein unerfahrener Benutzer hätte keine Chance.
IMSoP
Es ist nicht erforderlich, 1 USD zu verschieben. Nur exec "$@".
Reinierpost
$ (ln -s /bin/ls my-ls && exec my-ls) # bash: exec: my-ls: not found
Sourcejedi
(1) Es besteht keine Notwendigkeit shift $1; einfach exec ./"$@". (2) Da es sich um ein Shell-Skript handelt, ist es etwas sinnlos / irreführend, den Leuten zu raten, keinen .Befehl zu definieren , da es unmöglich ist, eine Datei mit dem Namen zu erstellen .. (Es ist möglich und sehr ratsam, einen Alias ​​oder eine Shell-Funktion mit dem Namen zu definieren ..)
Scott,
1

Wenn wir Hilfsskripte erstellen dürfen, können Sie einen Helfer erstellen, der das pwd zum PATH hinzufügt, und dann ausführen

. pathhelper    #adds pwd to path
file            #now it can be run without ./

Dies vermeidet das Hinzufügen von "." auf den Pfad und verschmutzen Sie Ihr .profile mit jedem Pfad, in dem Sie irgendwann etwas ausführen möchten.

Wir können diesen Ansatz noch einen Schritt weiter gehen, indem wir einen Helfer erstellen, der eine neue Shell mit einem modifizierten PATH startet. Wenn ein Verzeichnis als Parameter verwendet wird (standardmäßig wird pwd verwendet), funktioniert es wie ein pushd, das den Pfad bearbeitet. Möglicherweise müssen Sie sich bewusst sein, dass Änderungen an anderen Umgebungsvariablen beim Verlassen der Subshell verloren gehen, aber in einer lang laufenden Shell wird Ihre PATH-Variable nicht überfüllt sein. Abhängig von Ihren Arbeitsabläufen kann dies vorteilhaft sein.

:outer shell prompt$; subshellpathhelper    # launches a subshell with modified PATH
: subshell prompt $ ; file                  # in the subshell it can be run without ./

Aber ich denke, wenn Sie damit laufen wollten, könnten Sie hacken pushdund popdso können sie die gleichen Änderungen am Pfad vornehmen, ohne eine Subshell zu erstellen, die andere Änderungen verliert.

pushd --path ~/some/path/    # normal pushd plus adds target to path
file                         # it can be run without ./ until you popd

(Mit kann man nicht dasselbe machen, cdda es kein Analogon zu hat popd.)

Sie können auch ein spezielles Hilfspaar erstellen, um PATH-Einträge zu verschieben und zu platzieren. Was am besten funktioniert, hängt wirklich von Ihren Nutzungsmustern ab.

ShadSterling
quelle
Eigentlich könnten Sie so etwas tun cd, aber es ist noch weiter draußen: Erstellen Sie eine Datei wie .dircmdsund hacken Sie cd, um die in ./.dircmdsnicht verfügbar definierten Befehle direkt vor dem Umschalten und direkt nach dem Umschalten verfügbar zu machen .
ShadSterling
-1

Sie können die . script.shSyntax verwenden, solange sich das Skript, das Sie ausführen möchten, im aktuellen Verzeichnis befindet.

Sie können dem Interpreter auch ein Präfix voranstellen, z. B. sh oder bash. Beispiel:bash script.sh

UltimateByte
quelle
8
. script.shbricht ab, wenn das Skript enthält exit, hat unerwartete Auswirkungen, z. B. wenn PATH "vorübergehend" neu definiert wurde; Es funktioniert auch nur für Skripte für Ihre aktuelle Shell
sourcejedi
@sourcejedi Was exitSie betrifft , könnten Sie es in runde Klammern setzen, dh in eine Subshell, aber wahr, es wäre immer noch nur für Skripte in derselben Shell.
6.
Die Frage lautet "eine ausführbare Datei". Diese funktionieren für eine ausführbare Binärdatei nicht. nur für ein Skript. Und dein zweiter Absatz entspricht Zannas Antwort .
Scott
Nun, meine schlechte, ich führe meistens Bash-Sachen aus und entwickle sie, also ging ich davon aus, dass es sich um Bash-Skripte handelt :)
UltimateByte
Nicht nur für ein Skript, sondern nur für ein Bash-Skript.
Oskar Skog