comando bash / fish para imprimir la ruta absoluta a un archivo


Pregunta: ¿hay un simple sh / bash / zsh / fish/... comando para imprimir la ruta absoluta de cualquier archivo que lo alimente?

Caso de uso: Estoy en el directorio /a/b y me gustaría imprimir la ruta completa al archivo c en la línea de comandos para poder pegarlo fácilmente en otro programa: /a/b/c. Simple, sin embargo, un pequeño programa para hacer esto probablemente podría ahorrarme 5 o tan segundos cuando se trata de manejar caminos largos, que al final se suma. Así que me sorprende que no puedo encontrar una utilidad estándar para hacer esto - ¿realmente no hay ninguno?

Aquí hay una implementación de ejemplo, abspath.py:

#!/usr/bin/python
# Author: Diggory Hardy <[email protected]>
# Licence: public domain
# Purpose: print the absolute path of all input paths

import sys
import os.path
if len(sys.argv)>1:
    for i in range(1,len(sys.argv)):
        print os.path.abspath( sys.argv[i] )
    sys.exit(0)
else:
    print >> sys.stderr, "Usage: ",sys.argv[0]," PATH."
    sys.exit(1)
Author: dhardy, 2010-10-12

17 answers

Intenta realpath.

~ $ realpath example.txt
/home/username/example.txt
 351
Author: Benjamin Bannier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-29 10:29:34

Intenta readlink que resolverá enlaces simbólicos:

readlink -e /foo/bar/baz
 281
Author: Dennis Williamson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-12 14:34:06
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
 194
Author: dogbane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-05 07:51:05
$ readlink -m FILE
/path/to/FILE

Esto es mejor que readlink -e FILE o realpath, porque funciona incluso si el archivo no existe.

 72
Author: Flimm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-27 17:10:00

Olvídese de readlink y realpath que pueden o no estar instalados en su sistema.

Expandiendo la respuesta de dogbane aquí arriba se expresa como una función:

#!/bin/bash
get_abs_filename() {
  # $1 : relative filename
  echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}

Entonces puedes usarlo así:

myabsfile=$(get_abs_filename "../../foo/bar/file.txt")

Cómo y por qué funciona?

La solución aprovecha el hecho de que el comando integrado Bash pwd imprimirá la ruta absoluta del directorio actual cuando se invoque sin argumentos.

¿Por qué me gusta esta solución ?

Es portable y no requiere ni readlink ni realpath que a menudo no existe en una instalación predeterminada de una distribución Linux/Unix dada.

¿Y si dir no existe?

Como se indica anteriormente, la función fallará e imprimirá en stderr si la ruta de acceso al directorio dada no existe. Puede que esto no sea lo que quieres. Puede expandir la función para manejar esa situación:

#!/bin/bash
get_abs_filename() {
  # $1 : relative filename
  if [ -d "$(dirname "$1")" ]; then
    echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
  fi
}

Ahora devolverá una cadena vacía si uno de los dirs padre no existir.

¿Cómo se maneja el trailing '..' o '.'in input ?

Bueno, da un camino absoluto en ese caso, pero no uno mínimo. Se verá como:

/Users/bob/Documents/..

Si desea resolver el '..'necesitarás hacer el script como:

get_abs_filename() {
  # $1 : relative filename
  filename=$1
  parentdir=$(dirname "${filename}")

  if [ -d "${filename}" ]; then
      echo "$(cd "${filename}" && pwd)"
  elif [ -d "${parentdir}" ]; then
    echo "$(cd "${parentdir}" && pwd)/$(basename "${filename}")"
  fi
}
 68
Author: peterh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-24 20:55:47

Esta ruta relativa al convertidor de ruta absoluta función shell

  • no requiere utilidades (solo cd y pwd)
  • funciona para directorios y archivos
  • maneja .. y .
  • maneja espacios en dir o nombres de archivo
  • requiere que el archivo o directorio exista
  • no devuelve nada si no existe nada en la ruta dada
  • maneja rutas absolutas como entrada (las pasa a través de esencialmente)

Código:

function abspath() {
    # generate absolute path from relative path
    # $1     : relative filename
    # return : absolute path
    if [ -d "$1" ]; then
        # dir
        (cd "$1"; pwd)
    elif [ -f "$1" ]; then
        # file
        if [[ $1 = /* ]]; then
            echo "$1"
        elif [[ $1 == */* ]]; then
            echo "$(cd "${1%/*}"; pwd)/${1##*/}"
        else
            echo "$(pwd)/$1"
        fi
    fi
}

Muestra:

# assume inside /parent/cur
abspath file.txt        => /parent/cur/file.txt
abspath .               => /parent/cur
abspath ..              => /parent
abspath ../dir/file.txt => /parent/dir/file.txt
abspath ../dir/../dir   => /parent/dir          # anything cd can handle
abspath doesnotexist    =>                      # empty result if file/dir does not exist
abspath /file.txt       => /file.txt            # handle absolute path input

Nota: Esto se basa en las respuestas de nolan6000 y bsingh, pero corrige el caso del archivo.

También entiendo que la pregunta original era sobre una utilidad de línea de comandos existente. Pero ya que esta parece ser la pregunta en stackoverflow para que incluya scripts de shell que quieran tener dependencias mínimas, puse esta solución de script aquí, para que pueda encontrarla más tarde :)

 55
Author: Alexander Klimetschek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-20 20:48:55

El comando find puede ayudar

find $PWD -name ex*
find $PWD -name example.log

Lista todos los archivos dentro o debajo del directorio actual con nombres que coinciden con el patrón. Puede simplificarlo si solo obtiene unos pocos resultados (por ejemplo, directorio cerca de la parte inferior del árbol que contiene pocos archivos), solo

find $PWD

Uso esto en Solaris 10, que no tiene las otras utilidades mencionadas.

 23
Author: lessthanideal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-03 13:36:37

Si no tiene utilidades readlink o realpath, puede usar la siguiente función que funciona en bash y zsh (no estoy seguro del resto).

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

Esto también funciona para archivos inexistentes (al igual que la función python os.path.abspath).

Desafortunadamente abspath ./../somefile no se deshace de los puntos.

 14
Author: hluk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-12 18:28:01

Aquí hay una función de solo zsh que me gusta por su compacidad. Utiliza el modificador de expansión ' A ' - ver zshexpn(1).

realpath() { for f in "$@"; do echo ${f}(:A); done }
 9
Author: wjv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-24 13:59:37

Generalmente no hay tal cosa como el absolute path a un archivo (esta declaración significa que puede haber más de uno en general, por lo tanto el uso del artículo definido el no es apropiado). Un absolute path es cualquier ruta que comienza desde la raíz "/" y designa un archivo sin ambigüedad independientemente del directorio de trabajo.(ver por ejemplo wikipedia).

A relative path es una ruta que se debe interpretar a partir de otro directorio. Puede ser el directorio de trabajo si es un relative path siendo manipulado por una aplicación (aunque no necesariamente). Cuando está en un enlace simbólico en un directorio, generalmente se pretende que sea relativo a ese directorio (aunque el usuario puede tener otros usos en mente).

Por lo tanto, una ruta absoluta es solo una ruta relativa al directorio raíz.

Una ruta (absoluta o relativa) puede o no contener enlaces simbólicos. Si no lo hace, también es algo impermeable a los cambios en la estructura de enlace, pero esto no es necesariamente necesario o incluso deseable. Algunas personas llaman canonical path (o canonical file name o resolved path) un absolute path en el que todos los enlaces simbólicos han sido resueltos, es decir, han sido reemplazados por una ruta a la que se vinculan. Los comandos realpath y readlink buscan un camino canónico, pero solo realpath tiene una opción para obtener un camino absoluto sin molestarse en resolver enlaces simbólicos (junto con varias otras opciones para obtener varios tipos de caminos, absolutos o relativos a algunos directorio).

Esto requiere varias observaciones:

  1. los enlaces simbólicos solo se pueden resolver si lo que se supone que deben enlace a ya está creado, que obviamente no siempre es el caso. Los comandos realpath y readlink tienen opciones para explicar esto.
  2. un directorio en una ruta puede convertirse más tarde en un enlace simbólico, lo que significa que la ruta ya no es canonical. De ahí que el concepto dependa del tiempo (o del entorno).
  3. incluso en el caso ideal, cuando todos los enlaces simbólicos se pueden resolver, todavía puede haber más de uno canonical path a un archivo, para dos motivo:
    • la partición que contiene el archivo puede haber sido montada simultáneamente (ro) en varios puntos de montaje.
    • puede haber enlaces duros al archivo, lo que significa que esencialmente el archivo existe en varios directorios diferentes.

Por lo tanto, incluso con la definición mucho más restrictiva de canonical path, puede haber varias rutas canónicas a un archivo. Esto también significa que el calificador canonical es algo inadecuado ya que generalmente implica una noción de unicidad.

Esto amplía una breve discusión del tema en una respuesta a otra pregunta similar en Bash: recuperar ruta absoluta dada relativa

Mi conclusión es que realpath está mejor diseñado y mucho más flexible que readlink. El único uso de readlink que no está cubierto por realpath es la llamada sin opción que devuelve el valor de un enlace simbólico.

 8
Author: babou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:54

Para los directorios dirname se dispara para ../ y devuelve ./.

La función de Nolan6000 se puede modificar para corregir eso:

get_abs_filename() {
  # $1 : relative filename
  if [ -d "${1%/*}" ]; then
    echo "$(cd ${1%/*}; pwd)/${1##*/}"
  fi
}
 3
Author: bsingh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:11

He colocado el siguiente script en mi sistema y lo llamo como un alias de bash para cuando quiero tomar rápidamente la ruta completa a un archivo en el directorio actual:

#!/bin/bash
/usr/bin/find "$PWD" -maxdepth 1 -mindepth 1 -name "$1"

No estoy seguro de por qué, pero, en OS X cuando se llama por un script "PW PWD" se expande a la ruta absoluta. Cuando se llama al comando find en la línea de comandos, no lo hace, pero hace lo que quiero... disfrutar.

 3
Author: fred.johnsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-21 05:50:28

El dogbane respuesta con la descripción de lo que viene:

#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"

Explicación:

  1. Este script obtiene la ruta relativa como argumento "$1"
  2. Luego obtenemos dirname parte de esa ruta (puede pasar ya sea dir o file a este script): dirname "$1"
  3. Luego cd "$(dirname "$1") en este directorio relativo y obtenemos la ruta absoluta para él ejecutando pwd shell command
  4. Después de eso añadimos basename a la ruta absoluta: $(basename "$1")
  5. As paso final que echo
 2
Author: Eugen Konkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:47
#! /bin/bash

file="$@"
realpath "$file" 2>/dev/null || eval realpath $(echo $file | sed 's/ /\\ /g')

Esto compensa las deficiencias de realpath, guárdelo en un script de shell fullpath. Ahora puede llamar a:

$ cd && touch a\ a && rm A 2>/dev/null 
$ fullpath "a a"
/home/user/a a
$ fullpath ~/a\ a
/home/user/a a
$ fullpath A
A: No such file or directory.
 1
Author: ShellFish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-19 11:53:39

Esto no es una respuesta a la pregunta, sino para aquellos que hacen scripting:

echo `cd "$1" 2>/dev/null&&pwd||(cd "$(dirname "$1")";pwd|sed "s|/*\$|/${1##*/}|")`

Maneja / .. ./ etc correctamente. También parece trabajar en OSX

 1
Author: Alek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-16 18:57:03

Una alternativa para obtener la ruta absoluta en Ruby:

realpath() {ruby -e "require 'Pathname'; puts Pathname.new('$1').realpath.to_s";}

Funciona sin argumentos (carpeta actual) y la ruta de archivo o carpeta relativa y absoluta como agument.

 1
Author: Atika,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-10 16:16:06

Hola chicos, sé que es un hilo viejo, pero solo estoy publicando esto como referencia a cualquier otra persona que visitó esto como yo. Si entendí la pregunta correctamente, creo que el comando locate $filename. Muestra la ruta absoluta del archivo suministrado, pero solo si existe.

 -1
Author: icyyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-05 12:01:05