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