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

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

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

Здесь пример реализации, 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)

Ответ 1

Попробуйте realpath.

~ $ realpath .bashrc
/home/username/.bashrc

Ответ 2

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

readlink -e /foo/bar/baz

Ответ 3

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

Ответ 4

$ readlink -m FILE
/path/to/FILE

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

Ответ 5

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

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

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

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

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

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

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

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

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

Что делать, если dir не существует?

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

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

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

Как вы обрабатываете трейлинг ".." или ".". на входе?

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

/Users/bob/Documents/..

Если вы хотите разрешить "..", вам нужно сделать script следующим:

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
}

Ответ 6

Этот относительный путь к конвертеру абсолютного пути Функция оболочки

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

код:

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
}

Пример:

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

Ответ 7

Команда find может помочь

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

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

find $PWD

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

Ответ 8

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

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

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

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

Ответ 9

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

realpath() { for f in "[email protected]"; do echo ${f}(:A); done }

Ответ 10

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

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

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

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

Это вызывает несколько замечаний:

  • символические ссылки могут быть разрешены только в том случае, если они ссылка уже создана, что, очевидно, не всегда так. Команды realpath и readlink имеют опции для учета этого.
  • каталог на пути позже может стать символьной ссылкой, что означает, что путь больше не canonical. Следовательно, понятие зависит от времени (или окружающей среды).
  • даже в идеальном случае, когда все символические ссылки могут быть разрешены, в файле может быть больше одного canonical path, для двух причины:
    • раздел, содержащий файл, может быть установлен одновременно (ro) на нескольких точках подключения.
    • могут быть жесткие ссылки на файл, что означает, что файл существует в нескольких разных каталогах.

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

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

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

Ответ 11

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

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

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

Ответ 12

Для каталогов dirname происходит сбой для ../ и возвращает ./.

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

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

Ответ 13

#! /bin/bash

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

Это компенсирует недостатки realpath, сохраните его в оболочке script 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.

Ответ 14

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

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

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

Ответ 15

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

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

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

Ответ 16

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

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

Пояснение:

  • Этот script получает относительный путь как аргумент "$1"
  • Затем мы получаем часть dirname этого пути (вы можете передать либо dir или файл в этот script): dirname "$1"
  • Затем мы cd "$(dirname "$1") в этот относительный dir и получаем для него абсолютный путь, запустив pwd команду оболочки
  • После этого мы добавляем базовое имя к абсолютному пути: $(basename "$1")
  • В качестве последнего шага мы echo it

Ответ 17

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