Vraag Waarom moet ik `. /` Typen voordat een programma in de huidige map wordt uitgevoerd?


Tijdens het uitvoeren van een C-programma, a.out, met behulp van de Ubuntu-terminal, waarom moet ik altijd typen ./ voor a.out, in plaats van gewoon schrijven a.out? Is hier een oplossing voor?


86
2017-07-16 11:58


oorsprong


een beetje meer info: de punt is een afkorting voor 'source', wat een ingebouwd commando is van de bash-shell. meer over het bevel kan worden verkregen door herziening van 'man bash'. - Nathan
@nathan nee dat is het niet, de . in dit voorbeeld is de huidige werkmap. De source steno is . file.sh d.w.z. met een spatie, niet een /. U kunt geen gecompileerd programma vinden: ELF! = Bash ... - tobyodavies
@tobyodavies bedankt voor het verduidelijken - ik was zelfs verward over de verschillen tussen ./ en . - Nathan
Dit MOET een duplicaat zijn. Dit is het eerste dat iedereen tegenkomt bij het maken van hun eigen programma op UniX / Linux. - Peter Mortensen
Andere kandidaten voor duplicaat: Mijn programma kan niet worden uitgevoerd met de fout "opdracht niet gevonden" en Wat is de betekenis van ./ voor een bepaald pad?. - Peter Mortensen


antwoorden:


Wanneer u de naam van een programma typt, zoals a.out het systeem zoekt naar het bestand in uw PATH. Op mijn systeem is PATH ingesteld op

/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

De jouwe is waarschijnlijk vergelijkbaar. Om te controleren, voer in echo $PATH in een terminal.

Het systeem kijkt door deze mappen in de gegeven volgorde en als het niet kan vinden, produceert het programma een command not found fout.

De opdracht voorbereiden met ./ zegt effectief: "vergeet het PATH, ik wil dat je alleen in de huidige map kijkt".

Op dezelfde manier kun je het systeem vertellen om alleen op een andere specifieke locatie te kijken door de opdracht voor te doen met een relatief of absoluut pad, zoals:

../ betekent in de bovenliggende map bijv ../hello zoek hallo in de bovenliggende map.

./Debug/hello : "zoeken hello in de submap Debug van mijn huidige map. "

of /bin/ls : "zoeken ls in de directory /bin"

Standaard bevindt de huidige map zich niet in het pad omdat deze wordt beschouwd als een beveiligingsrisico. Zien Waarom is . niet standaard in het pad? op Superuser voor waarom.

Het is mogelijk om de huidige map toe te voegen aan uw PATH, maar om de redenen die worden gegeven in de gekoppelde vraag, zou ik het niet aanbevelen.


113
2017-07-16 13:20



Deze. 1 Niet doen toevoegen . aan jouw PATH (zoals de andere 2 antwoorden momenteel suggereren) vanwege het beveiligingsrisico dat in dit antwoord wordt genoemd. - Day
Het is misschien ook de moeite waard om op te merken dat er niets bijzonders aan is . hier kunt u een volledig of relatief pad naar een uitvoerbaar bestand gebruiken, bijvoorbeeld /home/user/foo/a.out of ./build/a.out - tobyodavies
@tobyodavies; Werkelijk . is speciaal omdat het "mijn huidige map" betekent en dus kan elke map zijn waar de gebruiker zichzelf vindt met lees- en uitvoeringsrechten. Dit is potentieel gevaarlijker dan het toevoegen van een specifiek volledig gekwalificeerd pad. - Warren Hill
@WarrenHill wanneer je overweegt het op je pad toe te voegen, ja het is heel anders. Echter in termen van bash-syntaxis, . heeft geen speciale status, het is gewoon een pad dat net zo goed kan beginnen / en ./blah zou net zo goed werken met cat of grep als een bash-prompt. - tobyodavies
@tobyodavies: OK Ik heb mijn antwoord bewerkt om uw punt op te nemen. - Warren Hill


De reden hiervoor is simpel.

Stel dat u een opdracht met dezelfde naam hebt als een toepassing in de huidige map. Het uitvoeren van de opdracht in de shell zou dan uw app oproepen in plaats daarvan van de ingebouwde opdracht. Dit zou een beveiligingsprobleem zijn als niets anders.

Door te eisen ./ om van te voren gebruikt te worden, weet de shell dat je de applicatie met de opgegeven naam wilt uitvoeren en niet een ingebouwde opdracht met die naam.


24
2017-12-16 03:21



3 hand details 3 hand details4040 details40 3 details details hand hand40 hand 3 details details4040 details 3 Bedankt dat het zinvol is (en ik geloof dat ik het een paar jaar geleden heb gehoord - moet dit keer lang genoeg bij Linux blijven, zodat dit spul in kan zinken) - Doug
je uitleg is misleidend, er is een verschil tussen ingebouwde commando's in een shell en uitvoerbare bestanden die toegankelijk zijn via de variabele PATH. Trouwens, je antwoord, hoe meer ik lees, voelt meer onjuist. - Ahmed Masud


./ voert bestanden uit die niet in uw bestand zijn $PATH, in plaats daarvan voert het het bestand uit in de huidige map (of een ander via ./home/stefano/script.sh). Nu is PATH een omgevingsvariabele die alle plaatsen bevat waar bash kan zoeken naar uitvoerbare programma's, zonder het volledige pad (absoluut) naar hen te hebben.

Deze scheiding is nodig om te voorkomen dat het verkeerde bestand wordt uitgevoerd. D.w.z. als je een bestand hebt met de naam ls in je thuismap voorkomt het niet in je PATH dat bash het met het echte verwart ls. De variabele PATH definieert ook de zoekvolgorde:

  • Wanneer u een opdracht uitvoert of een programma probeert een te maken exec syscall (een speciale methode van de kernel, hoe programma's worden gestart), zoekt het systeem naar het bestand door elk van de mappen in uw PATH te doorlopen. Als het programma eenmaal is gevonden, zelfs als het zich in meerdere mappen bevindt, wordt de zoekopdracht onderbroken en de eerste gevonden.

Om een ​​bestand uit te voeren, moet u het uitvoerbare bit in de rechten instellen:

  • Omdat je al op de commandoregel staat, kun je gewoon typen chmod +x finename.

  • Of u kunt de rechten instellen door met de rechtermuisknop op het bestand te klikken en te selecteren eigenschappen:

    alt text

U kunt het bestand nu naar een van de mappen in PATH kopiëren om te zien welke daar zijn - en ze zijn per gebruiker ingesteld - type echo $PATH.

stefano@3000-G530:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Als u een uitvoerbaar bestand maakt, caten verplaats het naar /usr/local/sbin, het wordt uitgevoerd in plaats van het juiste cat, waarin zich bevindt /bin. U kunt achterhalen waar uw bestanden zich bevinden type cat en whereis cat.


16
2017-12-16 03:18



Eén ding om op te merken: zijn vraag lijkt aan te geven dat hij iets heeft gecompileerd en gelinkt gcc, die automatisch de execute-bit instelt. - Nathan Osman


Waarom moet je typen? ./ voor het uitvoeren van een programma?

In de terminal, laten we zeggen wanneer je de naam van een applicatie typt gedit, de terminal zal gaan kijken in een aantal (vooraf gedefinieerde) mappen die applicaties bevatten (de binaries van de applicaties). De namen van deze mappen bevinden zich in een variabele genaamd PATH. Je kunt zien wat er in deze variabele zit door het uit te voeren echo $PATH. Zie die mappen gescheiden door :? Dat zijn de mappen waar de terminal naar zal zoeken, als je gewoon typt gedit, nautilusof a.out. Zoals je kunt zien, is het pad van jouw a.out programma is er niet. Wanneer je dat doet ./a.out, je vertelt de terminal "kijk in de huidige map en voer uit a.outen ga niet naar binnen kijken PATH.

Oplossing 1

Als je niet wilt typen ./ elke keer moet je toevoegen a.out's map in $PATH. In de volgende instructies neem ik aan dat het pad naar a.out is /path/to/programs/, maar je zou het moeten veranderen in je eigenlijke pad.

  1. Voeg eenvoudig de volgende regel toe aan het einde van het bestand ~/.pam_environment:

    PATH DEFAULT=${PATH}:/path/to/programs
    

    Bron: Persistente omgevingsvariabelen

  2. Log uit en log weer in. Je kunt nu uitvoeren a.out zonder ./ vanuit elke map.

Als u andere programma's in andere mappen hebt, kunt u deze gewoon toevoegen aan de bovenstaande regel. Ik zou echter adviseren om één directory met de naam "myPrograms" te hebben en al uw programma's eronder te plaatsen.

Oplossing 2

Notitie: verandering userName naar je echte Ubuntu-gebruikersnaam.

Wat als u andere programma's hebt die u wilt uitvoeren? En ze bevinden zich allemaal in verschillende mappen? Nou, een "meer georganiseerde" oplossing zou zijn om een ​​map genaamd bin onder uw homedirectory en voeg symbolische koppelingen (snelkoppelingen) onder die map toe. Hier is hoe:

  1. mkdir /home/userName/bin

    • Hiermee wordt de map gemaakt bin onder uw homedirectory.
  2. ln -s /path/to/programs/a.out /home/userName/bin

    • Hierdoor wordt een "symbolische link" (in principe een snelkoppeling) van uw gemaakt a.out programma onder bin.
  3. Log uit en log weer in. Je kunt nu uitvoeren a.out zonder ./ vanuit elke map.

Nu, als je ergens anders een ander programma hebt, laten we zeggen het programma b.in op uw bureaublad, alles wat u hoeft te doen is: ln -s /home/userName/Desktop/b.in /home/userName/bin, en je kunt het dan zonder uitvoeren ./ ook.

Notitie: dankzij @ Joe's commentaar, wanneer u back-ups maakt, moeten symbolische koppelingen speciaal worden afgehandeld. Standaard, rsync verwerkt ze helemaal niet, dus als je ze herstelt, zijn ze er niet.


11
2017-07-16 13:27



Dit is een handige truc als het spaarzaam wordt gebruikt. Als u er veel gebruik van maakt, doet uw systeem dingen die iemand anders niet zou verwachten. Ook wanneer u back-ups maakt, moeten symlinks speciaal worden afgehandeld. Standaard, rsync verwerkt ze helemaal niet, dus als je herstelt zijn ze er niet. - Joe


Zoals George in zijn antwoord opmerkte, helpt dit je op te merken dat je uitvoeren een bestand in de huidige werkdirectory (pwd).

Ik herinner me dat ik deze vraag al heel lang geleden aan mijn ouder had gesteld, zei hij . op mijn pad zodat wanneer ik dat doe a.out het ziet er in de huidige map uit en voert dat uit. In dit geval hoef ik het niet te doen ./a.out.

Maar persoonlijk zou ik het aanbevelen. Het is mij nooit overkomen, maar als je in een buitenaardse netwerkdirectory zit of zo, en een kwaadaardig, uitvoerbaar bestand genaamd ls bestaat daar, dan hebben . op je pad is een heel slecht idee. Niet dat u dit probleem heel vaak zult tegenkomen, gewoon zeggen.


1
2017-12-16 03:32



ok, Stefano keurde zijn antwoord goed om deze info te bevatten :) - Shrikant Sharat
Ik ben het er helemaal mee eens dat ik het niet heb toegevoegd . naar $PATH. 4040 hand details4040 3 details details 3 3 3 3 3 3 3 details 3 details 3 3 3 3 3 - Nathan Osman


Een './' is logisch als u een programma uitvoert dat bekend is voor u en specifiek, bijvoorbeeld je eigen. Dit programma moet aanwezig zijn in uw huidige directory. Een './' heeft geen zin als je een standaard commando uitvoert dat ergens in de $ PATH staat. Een commando "welke opdracht om te starten" vertelt je waar de opdracht om te draaien zich in de $ PATH bevindt.


0
2017-12-16 11:06





$ gcc hello.c -o /path/to/someplace/hello

zal op een bepaalde locatie een uitvoerbaar bestand produceren. Als die locatie op uw pad is, kunt u het bestand uitvoeren. Je kunt dit scripten als je een label voor de actie wilt maken "compileer deze broncode met behulp van de gcc en plaats een uitvoerbaar bestand op een bepaalde locatie die op je pad is"

Ik zou willen voorstellen dat je een nieuwe map met de naam "testbin" of iets dergelijks maakt en deze op je pad zet om je bestaande padmappen schoon te houden.


0
2017-07-16 18:35





./ elimineert onnodig zoeken naar een pad. ./ dwingen om alleen in de huidige map te zoeken. Als we niet geven ./ dan zoekt het naar verschillende paden die in het systeem zijn ingesteld /usr/bin, /usr/sbin/, enz.


0
2017-07-17 11:11





"./" betekent dat u een bestand in de huidige map wilt uitvoeren als een snelkoppeling om bijvoorbeeld het hele pad te typen:

[root@server ~]#/path/to/file/file.pl

is hetzelfde als:

[root@server file]#./file.pl

in het vorige voorbeeld hebt u de map en bijbehorende sup-directory's doorlopen naar de bestandslocatie en "./" gebruikt om het bestand in de huidige map uit te voeren.

de een ervoor "[root @ server ~] # / pad / naar / bestand / file.pl"zal ook het bestand uitvoeren als je lui bent om naar de bestandslocatie te" cd ".


0
2018-04-25 00:20





Het is heel eenvoudig en heeft veel toepassingen.

  1. Wanneer meerdere versies van dezelfde applicatie zijn geïnstalleerd, is deze beschikbaar in een ander pad, maar er kan een zachte link naar uw binary worden gemaakt /usr/bin. Python 2.7, Python 2.6 is bijvoorbeeld geïnstalleerd, maar / usr / bin / python -> python2.7 / usr / local / bin / python -> python2.6

Als je op het pad bent /usr/local/bin en voert Python uit, het zal altijd Python 2.7 uitvoeren. opgeven . neemt het uitvoerbare bestand van de huidige map.

  1. . - vertegenwoordigt altijd uitvoeren vanuit de huidige map. En .. betekent altijd uitvoeren vanuit de vorige map.

-4
2017-07-17 09:12