команда 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 311

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 или имена
  • требуется, чтобы файл или каталог существовал
  • ничего не возвращает, если на данном пути ничего не существует
  • ручки абсолютные пути в качестве входных данных (пропускает их через себя по существу)

код:

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 для этого, включая сценарии оболочки, которые хотят иметь минимальные зависимости, я поставил этот скрипт решение здесь, так что я могу найти его позже:)

The может поможет

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 }

там вообще нет такого понятия, как theabsolute 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. даже в идеальном случае, когда все символические ссылки могут быть решены, тут еще может быть больше, чем один canonical path в файл, для двух причины:
    • возможно, раздел, содержащий файл, был смонтирован одновременно (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" расширяется до абсолютного пути. Когда команда вызывается из командной строки, это не так. Но он делает то, что я хочу... наслаждаться.

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

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

объяснение:

  1. этот скрипт получает относительный путь в качестве аргумента ""
  2. тогда мы получим dirname часть этого пути (вы можете передать либо dir, либо файл в этот скрипт):dirname ""
  3. затем мы cd "$(dirname "") в этот относительный dir и получить абсолютный путь для него, запустив pwd командная оболочка
  4. после этого мы добавить basename абсолютный путь: $(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.

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