Como obter o caminho completo de um arquivo no bash?

21

Gostaria de uma maneira fácil de obter o caminho completo para um arquivo. Eu atualmente digito isso:

echo `pwd`/file.ext

Tentando reduzi-lo, criei um alias do bash:

alias fp='echo `pwd`/'

Mas agora, se eu digitar fp file.ext, há um espaço que aparece entre o /e o file.ext.

Esse comando já existe e estou sentindo falta dele? Caso contrário, como eu criaria um apelido ou função no bash?

Jens Erat
fonte

Respostas:

29

Nos sistemas Linux, você deve ter readlinko projeto GNU coreutils instalado e pode fazer isso:

readlink -f file.ext

Os sistemas Debian / ubuntu podem ter o utilitário realpath instalado, o qual "fornece basicamente a mesma funcionalidade /bin/readlink -fdo pacote coreutils".

Doug Harris
fonte
readlink -f(ou realpath, que é um utilitário antigo mantido para compatibilidade), expandirá adicionalmente todos os links simbólicos, o que não é necessariamente desejável.
Gilles 'SO- stop being evil'
8
fyi: não funciona no macosx.
Akira
No meu mac, instalei o coreutils usando o homebrew e ele inclui realpath.
Doug Harris
7

Em vez do pwdcomando, use a PWDvariável (também está no POSIX):

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

Se você precisar dar suporte ao Windows, o reconhecimento de caminhos absolutos será mais complicado, pois cada porta das ferramentas unix possui suas próprias regras para converter caminhos de arquivos. Com Cygwin, use o cygpathutilitário.

Gilles 'SO- parar de ser mau'
fonte
Talvez a escolha seja sua, mas essa função não produzirá a nova linha.
CYrus
essa abordagem tem a vantagem de usar apenas shell-builtins, o que é mais rápido do que chamar binários externos. você deve deixar esse fato um pouco mais claro.
akira
4

para responder sua pergunta com o que você usa agora:

o alias se expande na posição em que você está digitando no momento. você digitou:

% fp<SPACE>file.ext

isso se torna

% echo `pwd`<SPACE>file.exe

você pode usar uma função para evitar isso:

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

você pode usar isso como de costume:

% fp file.ext
akira
fonte
Você precisa de aspas duplas em torno das substituições de variáveis ​​e comandos:echo "`pwd`/$1"
Gilles 'SO- stop be evil' (
@Gilles: em que circunstâncias?
Akira
2
@akira: Sempre use aspas duplas, a menos que você queira que o resultado da expansão seja tratado como um padrão de globbing e que os resultados do globbing sejam divididos em palavras. Aqui você está criando um único nome de arquivo, para que sejam necessárias aspas duplas (tente sua função com um arquivo chamado *em um diretório que contém outros arquivos).
Gilles 'SO- stop be evil'
o ' ' é globbed pelo shell (zsh no meu caso) e expandido antes que eles atinjam a função. fp *produz /tmp/4cc3ea0c1b34bdesde que esse é o primeiro parâmetro para a função. os outros parâmetros seriam os outros arquivos no diretório assim que eu tiver um arquivo chamado ' ', a função ainda funcionará conforme o esperado, chamando-o com "*" ou * ou *
akira
o bash é o "ruim" aqui, como parece, o bash produz o que você está se referindo.
Akira
3

Você pode usar:

realpath file.ext
cYrus
fonte
Eu não tenho esse. Onde é que isso veio?
frabjous
@frabjous: é específico para o Debian e derivados, e só será instalado se você tiver solicitado ou um pacote que depende dele.
Gilles 'SO- stop being evil'
Estou usando o Arch. Isso não é baseado no Debian, mas existe um pacote para ele no AUR de qualquer maneira. Não tenho certeza se vale a pena instalar se eu já tiver o readlink.
frabjous
Bem, isso é uma opção; ou você pode considerar uma função, consulte a resposta de Gilles . De qualquer forma, isso depende do uso real que você quer fazer com isso (estou curioso).
CYrus
@frabjous: Você não especificou em qual sistema está, mas se ele usa um gerenciador de pacotes baseado no Aptitude (Debian, Ubuntu, Mint, etc.), você pode digitar apt-cache search realpathpara revelar que os pacotes coreutils e plain ol ' realpath ambos contêm. Você pode digitar sudo apt-get install realpath(ou coreutils) para instalá-lo.
Michael Scheper
1

De /programming//a/3915420/5795941

Esta é a única maneira que é aceitável para mim. Não expande links como realpath e readlink e é a maneira clássica de fazer isso que eu já vi por toda parte.

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