¿Cómo obtener la ruta completa de un archivo en bash?

22

Me gustaría una manera fácil de obtener la ruta completa a un archivo. Actualmente escribo esto:

echo `pwd`/file.ext

Intentando acortarlo, hice un alias bash:

alias fp='echo `pwd`/'

Pero ahora si escribo fp file.ext, hay un espacio que aparece entre el /y el file.ext.

¿Ya existe dicho comando y me lo estoy perdiendo? Si no, ¿cómo haría para crear tal alias o función en bash?

Jens Erat
fuente

Respuestas:

30

En los sistemas Linux, debe tener readlinkinstalado el proyecto GNU coreutils y puede hacer esto:

readlink -f file.ext

Los sistemas Debian / ubuntu pueden tener instalada la utilidad realpath que "proporciona principalmente la misma funcionalidad que /bin/readlink -fen el paquete coreutils".

Doug Harris
fuente
readlink -f(o realpath, que es una utilidad más antigua mantenida por compatibilidad) expandirá adicionalmente todos los enlaces simbólicos, lo cual no es necesariamente deseable.
Gilles 'SO- deja de ser malvado'
8
FYI: no funciona en macosx.
akira el
En mi Mac, instalé coreutils usando homebrew e incluye realpath.
Doug Harris
7

En lugar del pwdcomando, use la PWDvariable (también está en POSIX):

fp () {
  case "$1" in
    /*) printf '%s\n' "$1";;
    *) printf '%s\n' "$PWD/$1";;
  esac
}

Si necesita admitir Windows, reconocer rutas absolutas será más complicado ya que cada puerto de herramientas Unix tiene sus propias reglas para traducir rutas de archivos. Con Cygwin, use la cygpathutilidad.

Gilles 'SO- deja de ser malvado'
fuente
Tal vez sea su elección, pero esta función no generará la nueva línea.
cYrus
Este enfoque tiene la ventaja de usar solo shell-builtins, que es más rápido que llamar a binarios externos. deberías dejar este hecho un poco más claro.
akira
4

para responder a su pregunta con lo que usa ahora:

el alias se expande en la posición donde está escribiendo en este momento. escribiste:

% fp<SPACE>file.ext

esto se convierte

% echo `pwd`<SPACE>file.exe

podría usar una función para evitar eso:

function fp() {
    echo `pwd`/"$1"
}

puedes usar eso como siempre:

% fp file.ext
akira
fuente
Necesita comillas dobles alrededor de las sustituciones de variables y comandos:echo "`pwd`/$1"
Gilles 'SO- deja de ser malvado'
@Gilles: ¿bajo qué circunstancias?
akira
2
@akira: utilice siempre comillas dobles a menos que desee que el resultado de la expansión se trate como un patrón global y que los resultados del global se dividan en palabras. Aquí está creando un solo nombre de archivo, por lo que se necesitan las comillas dobles (pruebe su función con un archivo llamado *en un directorio que contenga otros archivos).
Gilles 'SO- deja de ser malvado'
el ' ' es bloqueado por el shell (zsh en mi caso) y expandido antes de que toquen la función. fp *cede /tmp/4cc3ea0c1b34bya que ese es el primer parámetro para la función. los otros parámetros serían los otros archivos en el directorio. tan pronto como tengo un archivo llamado ' ' la función aún funciona como se esperaba, llamándola con "*" o * o *
akira
bash es el "malo" aquí como parece, bash rinde a lo que te estás refiriendo.
akira
3

Puedes usar:

realpath file.ext
Ciro
fuente
No tengo ese De donde viene eso?
frabjous
@frabjous: es específico de Debian y derivados, y solo se instalará si lo ha solicitado o un paquete que depende de él.
Gilles 'SO- deja de ser malvado'
Estoy usando Arch. Eso no está basado en Debian, pero de todos modos hay un paquete para él en el AUR. No estoy seguro si vale la pena instalarlo si ya tengo readlink.
frabjous
Bueno, esa es una opción; o puede considerar una función, vea la respuesta de Gilles . De todos modos, eso depende del uso real que quieras hacer con eso (tengo curiosidad).
cYrus
@frabjous: No especificó en qué sistema se encuentra, pero si utiliza un administrador de paquetes basado en Aptitude (Debian, Ubuntu, Mint, etc.), puede escribir apt-cache search realpathpara revelar que los paquetes coreutils y simple realpath ambos lo contienen. Luego puede escribir sudo apt-get install realpath(o coreutils) para instalarlo.
Michael Scheper
1

Desde /programming//a/3915420/5795941

Esta es la única forma que es aceptable para mí. No expande enlaces como realpath y readlink y es la forma clásica de hacerlo que he visto en todas partes.

#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Philippe Carphin
fuente