команда 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 ответов:
$ 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 }
там вообще нет такого понятия, как the
absolute path
к файлу (это утверждение означает, что может быть более одного в целом, следовательно, использование определенного артикля the не подходит). Анabsolute path
- Это любой путь, который начинается с корня " / " и обозначает файл без двусмысленности независимо от рабочего каталога.(см., например,Википедия).A
relative path
- это путь, который должен быть интерпретирован, начиная с другой каталог. Это может быть рабочий каталог, если этоrelative path
управляется приложением (хотя и не обязательно). Когда он находится в символической ссылке в каталоге, он обычно предназначен для того, чтобы быть относительно этого каталога (хотя пользователь может иметь в виду другие виды использования).следовательно, абсолютный путь-это просто путь относительно корневого каталога.
путь (абсолютный или относительный) может содержать или не содержать символические ссылки. Если это не так, это также несколько невосприимчивы к изменениям в связывающей структуре, но это не обязательно требуется или даже желательно. Некоторые люди называют
canonical path
( илиcanonical file name
илиresolved path
) anabsolute path
в котором все символические ссылки были разрешены, т. е. были заменены путем к тому, на что они ссылаются. Командыrealpath
иreadlink
оба ищут канонический путь, но толькоrealpath
имеет возможность получить абсолютный путь, не беспокоясь о разрешении символических ссылок (наряду с несколькими другими вариантами, чтобы получить различные вид путей, абсолютных или относительных к некоторому каталогу).это требует нескольких замечаний:
- символические ссылки могут быть разрешены только в том случае, если они должны ссылка на уже создана, что, очевидно, не всегда так. Команды
realpath
иreadlink
есть варианты для учета этого.- каталог на пути может позже стать символической ссылкой, Что означает, что путь больше не
canonical
. Следовательно, понятие времени (или окружающая среда) зависит.- даже в идеальном случае, когда все символические ссылки могут быть решены, тут еще может быть больше, чем один
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 "")"
объяснение:
- этот скрипт получает относительный путь в качестве аргумента
""
- тогда мы получим dirname часть этого пути (вы можете передать либо dir, либо файл в этот скрипт):
dirname ""
- затем мы
cd "$(dirname "")
в этот относительный dir и получить абсолютный путь для него, запустивpwd
командная оболочка- после этого мы добавить basename абсолютный путь:
$(basename "")
- в качестве заключительного шага мы
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