команда bash/fish для печати абсолютного пути к файлу

вопрос: есть ли простой sh/bash/zsh/fish/... команда для печати абсолютного пути к любому файлу, который я его кормлю?

случай использования: я в каталоге /a/b и я хотел бы напечатать полный путь к файлу c в командной строке, чтобы я мог легко вставить его в другую программу:/a/b/c. Простая, но небольшая программа для этого, вероятно, могла бы сэкономить мне 5 или около того секунд, когда дело доходит до обработки длинных путей, что в конце концов складывается. Поэтому меня удивляет, что я не могу найти стандартная утилита для этого-действительно ли ее нет?

вот пример реализации, abspath.py:

#!/usr/bin/python
# Author: Diggory Hardy <diggory.hardy@gmail.com>
# 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)

17 ответов


попробовать realpath.

~ $ realpath example.txt
/home/username/example.txt

попробовать readlink который разрешит символические ссылки:

readlink -e /foo/bar/baz

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

$ readlink -m FILE
/path/to/FILE

Это лучше, чем readlink -e FILE или realpath, потому что он работает, даже если файл не существует.


забудь о readlink и realpath который может быть установлен или не установлен в вашей системе.

расширения dogbane это выше здесь это выражается как функция:

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

вы можете использовать его следующим образом:

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

как и почему это работает?

решение использует тот факт, что встроенный Bash pwd команда напечатает абсолютный путь текущего каталога при вызове без аргументы.

почему мне нравится это решение ?

это портативный и не требует ни readlink или realpath который часто не существует при установке по умолчанию данного дистрибутива Linux/Unix.

что, если dir не существует?

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

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

теперь он вернет пустую строку, если один родительский dirs не существует.

как вы обрабатываете трейлинг '..' или.' - во вводе ?

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

/Users/bob/Documents/..

если вы хотите решить '.. вам нужно будет сделать скрипт типа:

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

  if [ -d "${filename}" ]; then
      echo "$(cd "${filename}" && pwd)"
  elif [ -d "${parentdir}" ]; then
    echo "$(cd "${parentdir}" && pwd)/$(basename "${filename}")"
  fi
}

этот относительный путь к абсолютному пути конвертер функция Shell

  • не требует никаких утилит (просто cd и pwd)
  • работает для каталогов и файлов
  • ручки .. и .
  • обрабатывает пробелы в dir или имена
  • требует, чтобы файл или каталог существовал
  • возвращает nothing, если ничего не существует в данном пути
  • ручки абсолютные пути в качестве входных данных (пропускает их через себя)

код:

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

пример:

# 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

Примечание: это основано на ответы от nolan6000 и bsingh, но исправляет дело.

я также понимаю, что первоначальный вопрос касался существующей утилиты командной строки. Но поскольку это, похоже, вопрос о stackoverflow для этого, включая сценарии оболочки, которые хотят иметь минимальные зависимости, я помещаю это решение скрипта здесь, поэтому я могу найти его позже:)


на может поможет

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

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

find $PWD

Я использую это на Solaris 10, в котором нет других упомянутых утилит.


Если у вас нет утилит readlink или realpath, вы можете использовать следующую функцию, которая работает в bash и zsh (не уверен в остальном).

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

Это также работает для несуществующих файлов (как и функция python os.path.abspath).

к сожалению abspath ./../somefile не избавляется от точек.


вот функция zsh-only, которая мне нравится за ее компактность. Он использует модификатор расширения " A " - см. zshexpn(1).

realpath() { for f in "$@"; do echo ${f}(:A); done }

обычно нет такой вещи, как the absolute path в файл (это утверждение означает, что может быть более одного в целом, следовательно, использование определенной статьи the не подходит). Ан absolute path - Это любой путь, который начинается с корня " / " и обозначает файл без двусмысленности независимо от рабочего каталога.(см., например,Википедия).

A relative path - это путь, который интерпретируется, начиная с другой каталог. Это может быть рабочий каталог, если это relative path манипулирование приложением (хотя и не обязательно). Когда он находится в символической ссылке в каталоге, он обычно предназначен для относительного этого каталога (хотя пользователь может иметь в виду другое использование).

следовательно, абсолютный путь-это просто путь относительно корневого каталога.

путь (абсолютный или относительный) может содержать или не содержать символические ссылки. Если это не так, это также несколько невосприимчивы к изменениям в структуре связей, но это не обязательно требуется или даже желательно. Некоторые люди называют canonical path ( или canonical file name или resolved path) an absolute path в котором все символические ссылки были разрешены, т. е. были заменены путем к тому, на что они ссылаются. Команды realpath и readlink оба ищут канонический путь, но только realpath имеет возможность получить абсолютный путь, не беспокоясь о разрешении символических ссылок (наряду с несколькими другими вариантами, чтобы получить различные вид путей, абсолютный или относительный к некоторому каталогу).

это требует нескольких замечаний:

  1. символические ссылки могут быть разрешены только в том случае, если они должны ссылка на уже создана, что, очевидно, не всегда так. Команды realpath и readlink есть варианты для учета этого.
  2. каталог на пути может позже стать символической ссылкой, Что означает, что путь больше не canonical. Следовательно, понятие-это время (или среды) зависит.
  3. даже в идеальном случае, когда все символические ссылки могут быть решены, может быть, их еще несколько!--4--> в файл, для двух причины:
    • раздел, содержащий файл, возможно, был смонтирован одновременно (ro) на нескольких точках крепления.
    • могут быть жесткие ссылки на файл, что означает, что файл существует в нескольких разных каталогах.

следовательно, даже с гораздо более ограничительное определение canonical path, там может быть несколько канонических путей к файлу. Это также означает, что квалификатор canonical несколько неадекватен, поскольку обычно подразумевает понятие уникальности.

это расширяет краткое обсуждение темы в ответе на другой аналогичный вопрос в Bash: получить абсолютный путь, заданный относительным

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


для каталогов dirname попадется на ../ и возвращает ./.

nolan6000 это можно изменить, чтобы исправить это:

get_abs_filename() {
  #  : relative filename
  if [ -d "${1%/*}" ]; then
    echo "$(cd ${1%/*}; pwd)/${1##*/}"
  fi
}

Я разместил следующий скрипт в своей системе , и я называю его псевдонимом bash, когда я хочу быстро захватить полный путь к файлу в текущем каталоге:

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

Я не уверен, почему, но в OS X при вызове скриптом "$PWD " расширяется до абсолютного пути. Когда команда find вызывается в командной строке, это не так. Но он делает то, что я хочу... наслаждаться.


The dogbane ответ С описанием того, что происходит:

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

объяснение:

  1. этот скрипт получает относительный путь в качестве аргумента ""
  2. тогда мы получим dirname часть этого пути (вы можете передать либо dir, либо файл в этот скрипт):dirname ""
  3. затем мы cd "$(dirname "") в этот относительный dir и получить абсолютный путь для него, запустив pwd shell command
  4. после этого мы добавить имени абсолютный путь: $(basename "")
  5. в качестве заключительного шага мы echo это

#! /bin/bash

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

это компенсирует недостатки realpath, хранить его в shell-скрипт fullpath. Теперь вы можете позвонить:

$ 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.

Это не ответ на вопрос, но для тех, кто делает скрипты:

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

он обрабатывает / .. ./ и т. д. Правильно. Я также, кажется, работаю над OSX


Альтернатива для получения абсолютного пути в Рубин:

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

работает без аргументов (текущая папка) и относительного и абсолютного пути к файлу или папке как agument.


Эй, ребята, я знаю, что это старая нить, но я просто публикую это для ссылки на кого-либо еще, кто посетил это, как я. Если я правильно понял вопрос, я думаю . Он отображает абсолютный путь к файлу, но только если он существует.