¿Por qué necesito escribir `. /` Antes de ejecutar un programa en el directorio actual?

92

Al ejecutar un programa en C a.out, usando el terminal de Ubuntu, ¿por qué siempre necesito escribir ./antes a.out, en lugar de solo escribir a.out? ¿Hay alguna solución para esto?

Prashant Chikhalkar
fuente

Respuestas:

119

Cuando escribe el nombre de un programa como a.outel sistema busca el archivo en su RUTA. En mi sistema, PATH está configurado en

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

El tuyo es probablemente similar. Para verificar, ingrese echo $PATHen una terminal.

El sistema mira a través de estos directorios en el orden dado y si no puede encontrar el programa produce un command not founderror.

Anteponer el comando con ./efectivamente dice "olvídate de la RUTA, quiero que mires solo en el directorio actual".

Del mismo modo, puede indicarle al sistema que busque solo en otra ubicación específica anteponiendo el comando con una ruta relativa o absoluta como:

../significa en el directorio principal, por ejemplo, ../hellobusque hola en el directorio principal.

./Debug/hello: "buscar helloen el subdirectorio Debug de mi directorio actual".

o /bin/ls: "buscar lsen el directorio /bin"

De manera predeterminada, el directorio actual no está en la ruta porque se considera un riesgo de seguridad. Ver por qué es. no en la ruta por defecto? en Superusuario por qué.

Es posible agregar el directorio actual a su RUTA, pero por las razones dadas en la pregunta vinculada, no lo recomendaría.

Warren Hill
fuente
25
Esta. +1 No agregue .a su PATH(como sugieren las otras 2 respuestas actualmente) debido al riesgo de seguridad mencionado en esta respuesta.
Día
8
También vale la pena señalar que no hay nada especial .aquí, puede usar una ruta completa o relativa a un ejecutable, por ejemplo, /home/user/foo/a.outo./build/a.out
tobyodavies
@tobyodavies; En realidad .es especial porque significa "mi directorio actual" y podría ser cualquier directorio en el que el usuario se encuentre con privilegios de lectura y ejecución. Esto es potencialmente más peligroso que agregar una ruta específica totalmente calificada.
Warren Hill
@WarrenHill cuando considere agregarlo a su ruta, sí, es bastante diferente. Sin embargo, en términos de sintaxis de bash, .no tiene un estado especial, es solo una ruta que podría comenzar con /y ./blahfuncionaría tan bien con cato grepcomo un indicador de bash.
tobyodavies
@tobyodavies: OK. Edité mi respuesta para incluir su punto.
Warren Hill
24

La razón de esto es simple.

Suponga que tiene un comando con el mismo nombre que una aplicación en el directorio actual. Luego, ejecutar el comando en el shell invocaría su aplicación en lugar del comando incorporado. Esto sería una preocupación de seguridad si nada más.

Al requerir ./que se use en frente, el shell sabe que desea ejecutar la aplicación con el nombre de pila y no un comando incorporado con ese nombre.

Nathan Osman
fuente
1
su explicación es engañosa, hay una diferencia entre los comandos integrados en un shell y los ejecutables a los que se puede acceder a través de la variable PATH. De hecho, su respuesta cuanto más leo, se siente más incorrecta.
Ahmed Masud
16

./ejecuta archivos que no están en su $PATH, más bien ejecuta el archivo en el directorio actual (u otra vía ./home/stefano/script.sh). Ahora, PATH es una variable de entorno que contiene todos los lugares donde bash puede buscar programas ejecutables, sin tener la ruta completa (absoluta) hacia ellos.

Esta separación es necesaria para evitar ejecutar el archivo incorrecto. Es decir, si tiene un archivo llamado lsen su directorio de inicio, no estar en su RUTA evitará que bash lo confunda con lo real ls. La variable PATH también define el orden de búsqueda:

  • Cuando ejecuta un comando, o un programa intenta realizar una execllamada al sistema (un método especial del Kernel, cómo se inician los programas), el sistema busca el archivo revisando cada uno de los directorios en su RUTA. Una vez que se ha encontrado el programa, incluso si está en varios directorios, la búsqueda se interrumpe y se ejecuta el primero encontrado.

Para ejecutar un archivo, deberá establecer el bit ejecutable en los permisos:

  • Como ya estás en la línea de comando, puedes escribir chmod +x finename.

  • O puede establecer los permisos haciendo clic derecho en el archivo y seleccionando Propiedades :

    texto alternativo

Ahora puede copiar el archivo a cualquiera de los directorios en PATH, para ver cuáles están allí, y están configurados por usuario, tipo echo $PATH.

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

Si crea un archivo ejecutable cat, y lo mueve /usr/local/sbin, se ejecuta en lugar del correcto cat, que reside en /bin. Puede averiguar dónde están sus archivos utilizando type caty whereis cat.

Stefano Palazzo
fuente
2
Una cosa a tener en cuenta: su pregunta parece indicar que ha compilado y vinculado algo gcc, lo que establece automáticamente el bit de ejecución.
Nathan Osman
12

¿Por qué necesita escribir ./antes de ejecutar un programa?

En el terminal, cada vez que escriba el nombre de una aplicación, digamos gedit, el terminal buscará en algunos directorios (predefinidos) que contienen aplicaciones (los binarios de las aplicaciones). Los nombres de estos directorios están contenidos en una variable llamada PATH. Puede ver lo que hay en esta variable ejecutando echo $PATH. ¿Ves esos directorios separados por :? Esos son los directorios que el terminal será ir a buscar adentro, si usted sólo tiene que escribir gedit, nautiluso a.out. Como puede ver, la ruta de su a.outprograma no está allí. Cuando lo hace ./a.out, le está diciendo a la terminal que "mire en el directorio actual, y ejecute a.out, y no vaya a buscar PATH.

Solución 1

Si no desea escribir ./todo el tiempo, deberá agregar a.outel directorio $PATH. En las siguientes instrucciones, supondré que la ruta a.outes /path/to/programs/, pero debe cambiarla a su ruta real.

  1. Simplemente agregue la siguiente línea al final del archivo ~/.pam_environment:

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

    Fuente: variables de entorno persistentes

  2. Cerrar la sesión y volver a iniciarla. Ahora va a ser capaz de ejecutar a.outsin ./desde cualquier directorio.

Si tiene otros programas en otros directorios, puede agregarlos a la línea anterior. Sin embargo, aconsejaría tener un directorio llamado "myPrograms", por ejemplo, y poner todos sus programas debajo.

Solución 2

Nota: cambie userNamea su nombre de usuario real de Ubuntu.

¿Qué pasa si tiene otros programas que desea ejecutar? ¿Y están todos en carpetas diferentes? Bueno, una solución "más organizada" sería crear una carpeta llamada binbajo su directorio de Inicio y agregar enlaces simbólicos (atajos) debajo de esa carpeta. Así es cómo:

  1. mkdir /home/userName/bin

    • Esto creará la carpeta bindebajo de su directorio de inicio.
  2. ln -s /path/to/programs/a.out /home/userName/bin

    • Esto creará un "enlace simbólico" (básicamente, un acceso directo) de su a.outprograma en bin.
  3. Cerrar la sesión y volver a iniciarla. Ahora va a ser capaz de ejecutar a.outsin ./desde cualquier directorio.

Ahora, cada vez que tenga otro programa en cualquier otro lugar, digamos que el programa b.inen su Escritorio, todo lo que necesita hacer es: ln -s /home/userName/Desktop/b.in /home/userName/biny luego podrá ejecutarlo sin él ./también.

Nota: gracias al comentario de @ Joe , cuando haces copias de seguridad, los enlaces simbólicos deben manejarse especialmente. Por defecto, rsyncno los procesa en absoluto, por lo que cuando restaura, no están allí.

Alaa Ali
fuente
1
Este es un truco útil si se usa con moderación. Usarlo mucho hace que su sistema haga cosas que alguien más no esperaría. Además, cuando haces copias de seguridad, los enlaces simbólicos deben manejarse especialmente. De forma predeterminada , rsync no los procesa en absoluto, por lo que cuando restaura no están allí.
Joe
1

Como George señaló en su respuesta, esto le ayuda a notar que está ejecutando un archivo en el directorio de trabajo actual ( pwd).

Recuerdo haberle hecho esta pregunta a mi superior hace mucho tiempo, dijo que debería agregar .a mi camino para que cuando lo haga, a.outse vea en el directorio actual y lo ejecute. En este caso no tengo que hacer ./a.out.

Pero, personalmente, recomendaría no hacerlo. Nunca me sucedió, pero si estás en un directorio de red alienígena o algo así y lsexiste un archivo ejecutable malicioso llamado allí, entonces tener .en tu camino es una muy mala idea. No es que te encuentres con este problema muy a menudo, solo digo.

Shrikant Sharat
fuente
ok, Stefano adoptó su respuesta para contener esta información :)
Shrikant Sharat
3
Estoy completamente de acuerdo con no agregar .a $PATH. Una idea muy peligrosa.
Nathan Osman
1

Además de otras respuestas, aquí la parte esencial a partir de la man bashcual se explica eso bien:

EJECUCIÓN DE MANDO
       Después de que un comando se haya dividido en palabras, si resulta en un simple
       comando y una lista opcional de argumentos, las siguientes acciones son
       tomado.

       Si el nombre del comando no contiene barras, el shell intenta localizar
       eso. Si existe una función de shell con ese nombre, esa función es
       invocado como se describe anteriormente en FUNCIONES. Si el nombre no coincide con un
       función, el shell lo busca en la lista de shell incorporados. Si
       se encuentra una coincidencia, se invoca esa construcción.

       Si el nombre no es una función de shell ni una función incorporada, y no contiene
       barras, bash busca en cada elemento de la RUTA un directorio con‐
       contener un archivo ejecutable con ese nombre.
mook765
fuente
0

Un './' tiene sentido cuando ejecuta un programa que es conocido por usted y específico, por ejemplo, el suyo propio. Este programa debe estar presente en su directorio actual. Un './' no tiene sentido cuando ejecuta un comando estándar que está en algún lugar de $ PATH. Un comando "which command-to-run" le dice dónde está el comando-to-run en $ PATH.

usuario7346
fuente
0
$ gcc hello.c -o /path/to/someplace/hello

producirá un ejecutable en alguna ubicación. Si esa ubicación está en su camino, podrá ejecutar el archivo. Puede escribir esto si desea crear una etiqueta para la acción "compile este código fuente usando el gcc y coloque un ejecutable en alguna ubicación que esté en su ruta"

Le sugiero que cree un nuevo directorio llamado "testbin" o algo por el estilo y lo coloque en su ruta para mantener limpios sus directorios de ruta existentes.

Jon Kiparsky
fuente
0

./elimina la búsqueda innecesaria de una ruta. ./forzar a buscar solo en el directorio actual. Si no damos ./a continuación, se buscará varias camino trazado en el sistema como /usr/bin, /usr/sbin/, etc.

usuario175959
fuente
0

"./" significa que desea ejecutar un archivo en el directorio actual, es un acceso directo para escribir la ruta completa, por ejemplo:

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

es igual que:

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

en el ejemplo anterior, recorrió el directorio y sus sup-directorios hasta la ubicación del archivo y utilizó "./" para ejecutar el archivo en el directorio actual.

el anterior " [root @ server ~] # / path / to / file / file.pl " también ejecutará el archivo si va a "cd" su camino a la ubicación del archivo.

Khaled Moustafa
fuente
-4

Es muy simple y tiene muchos usos.

  1. Cuando se instalan varias versiones de la misma aplicación, estará disponible en una ruta diferente, pero se puede crear un enlace suave a su binario /usr/bin. Por ejemplo, Python 2.7, Python 2.6 está instalado pero / usr / bin / python -> python2.7 / usr / local / bin / python -> python2.6

Si está en la ruta /usr/local/biny ejecuta Python, siempre ejecutará Python 2.7. La especificación .tomará el ejecutable de la carpeta actual.

  1. .- siempre representa ejecutar desde el directorio actual. Y ..siempre significa que se ejecuta desde el directorio anterior.
Ramjee Anna
fuente