Как получить полный путь к файлу в bash?


22

Я хотел бы получить простой способ получить полный путь к файлу. Я сейчас набираю это:

echo `pwd`/file.ext

Пытаясь сократить его, я сделал псевдоним bash:

alias fp='echo `pwd`/'

Но теперь , если я печатаю fp file.ext, есть пространство , которое появляется между /и file.ext.

Такая команда уже существует, и мне ее не хватает? Если нет, то как мне создать псевдоним или функцию в bash?

Ответы:


30

В системах Linux у вас должен быть readlinkустановлен проект GNU coreutils, и вы можете сделать это:

readlink -f file.ext

В системах Debian / Ubuntu может быть установлена утилита realpath, которая «предоставляет в основном те же функции, что и /bin/readlink -fв пакете coreutils».


readlink -f(или realpath, которая является более старой утилитой, сохраняемой для совместимости) дополнительно расширит все символические ссылки, что не обязательно желательно.
Жиль "ТАК - перестать быть злым"

8
К вашему сведению: не работает на Macosx.
Акира

На моем Mac я установил coreutils, используя homebrew, и он включает realpath.
Даг Харрис

7

Вместо pwdкоманды используйте PWDпеременную (она также в POSIX):

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

Если вам нужна поддержка Windows, распознавание абсолютных путей будет более сложным, поскольку у каждого порта инструментов Unix есть свои правила для преобразования путей к файлам. С Cygwin используйте cygpathутилиту.


Может быть, это ваш выбор, но эта функция не выведет новую строку.
cYrus

этот подход имеет преимущество использования только встроенных командных оболочек, что быстрее, чем вызов внешних двоичных файлов. Вы должны сделать этот факт немного более ясным.
Акира

4

чтобы ответить на ваш вопрос с тем, что вы используете прямо сейчас:

псевдоним расширяется в той позиции, где вы печатаете прямо сейчас. Вы ввели:

% fp<SPACE>file.ext

это становится

% echo `pwd`<SPACE>file.exe

Вы можете использовать функцию, чтобы избежать этого:

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

Вы можете использовать это как обычно:

% fp file.ext

Вам нужны двойные кавычки вокруг переменных и подстановок команд:echo "`pwd`/$1"
Жиль "ТАК, перестань быть злым"

@ Жиль: при каких обстоятельствах?
Акира

2
@akira: Всегда используйте двойные кавычки, если только вы не хотите, чтобы результат раскрытия рассматривался как шаблон глобинга, а результаты глобализации разбивать на слова. Здесь вы создаете одно имя файла, поэтому нужны двойные кавычки (попробуйте свою функцию с файлом, который называется *в каталоге, содержащем другие файлы).
Жиль "ТАК - перестань быть злым"

' ' скрывается оболочкой (в моем случае это zsh) и расширяется до того, как они попадают в функцию. fp *дает, /tmp/4cc3ea0c1b34bтак как это первый параметр для функции. другие параметры будут другими файлами в каталоге. как только у меня есть файл с именем ' ', функция все еще работает, как и ожидалось, вызывая его с помощью «*» или * или *
akira

Bash, как кажется, «плохой», bash дает то, к чему вы обращаетесь.
Акира

3

Ты можешь использовать:

realpath file.ext

У меня этого нет. Откуда это?
безумно

@frabjous: он специфичен для Debian и его производных и будет установлен, только если вы запросили его или пакет, который от него зависит.
Жиль "ТАК - перестать быть злым"

Я использую Arch. Он не основан на Debian, но в AUR есть пакет для него. Не уверен, что стоит установить, если у меня уже есть ссылка для чтения.
торжественно

Ну, это вариант; или вы можете рассмотреть функцию, см. ответ Жиля . Во всяком случае, это зависит от реального использования, которое вы хотите сделать с этим (мне любопытно).
cyrus

@frabjous: вы не указали, в какой системе вы находитесь, но если он использует менеджер пакетов на основе Aptitude (Debian, Ubuntu, Mint и т. д.), вы можете напечатать, apt-cache search realpathчтобы показать, что пакеты coreutils и plain ol ' realpath оба содержат это. Затем вы можете напечатать sudo apt-get install realpath(или coreutils), чтобы установить его.
Майкл Шепер

1

С /programming//a/3915420/5795941

Это единственный способ, который приемлем для меня. Не расширяет ссылки, такие как realpath и readlink, и это классический способ сделать это, который я видел повсюду.

#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.