Вопрос: существует ли команда 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)
Попробуйте realpath
.
~ $ realpath .bashrc
/home/username/.bashrc
Попробуйте readlink
, который разрешит символические ссылки:
readlink -e /foo/bar/baz
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
ab
(два пробела между a и b, SO ест один из них).
$ readlink -m FILE
/path/to/FILE
Это лучше, чем readlink -e FILE
или realpath
, потому что он работает, даже если файл не существует.
Забудьте о 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.
Как указано выше, функция будет терпеть неудачу и напечатать на 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
}
Этот относительный путь к конвертеру абсолютного пути Функция оболочки
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 здесь, поэтому я могу найти его позже:)
$ abspath 'ab c/file.txt'
Это потому, что аргумент cd
не заключен в кавычки. Чтобы преодолеть это, вместо цитирования всего аргумента в echo
(есть ли причина для этих кавычек?), Приводите только аргументы пути. Т.е. заменить echo "$(cd ${1%/*}; pwd)/${1##*/}"
на echo $(cd "${1%/*}"; pwd)/${1##*/}
Команда find
может помочь
find $PWD -name ex*
find $PWD -name example.log
Список всех файлов в или ниже текущего каталога с именами, соответствующими шаблону. Вы можете упростить его, если вы получите только несколько результатов (например, каталог около дна дерева, содержащего несколько файлов), просто
find $PWD
Я использую это в Solaris 10, у которого нет других упомянутых утилит.
PWD
, вы можете просто использовать $PWD/$filename
.
Если у вас нет утилит readlink или realpath, вы можете использовать следующую функцию, которая работает в bash и zsh (не уверены в остальном).
abspath () { case "$1" in /*)printf "%s\n" "$1";; *)printf "%s\n" "$PWD/$1";; esac; }
Это также работает для несуществующих файлов (как и функция python os.path.abspath
).
К сожалению, abspath ./../somefile
не избавляется от точек.
В файл обычно не входит 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
, - это вызов без опции, возвращающий значение символической ссылки.
realpath
против readlink
или даже о символических ссылках realpath
к тому, что я спросил.
Здесь функция zsh-only, которая мне нравится для ее компактности. Он использует модификатор расширения A - см. Zshexpn (1).
realpath() { for f in "$@"; do echo ${f}(:A); done }
В моей системе был помещен следующий script, и я называю его псевдонимом bash, когда хочу быстро захватить полный путь к файлу в текущем каталоге:
#!/bin/bash
/usr/bin/find "$PWD" -maxdepth 1 -mindepth 1 -name "$1"
Я не уверен, почему, но в OS X при вызове script "$ PWD" расширяется до абсолютного пути. Когда команда find вызывается в командной строке, это не так. Но он делает то, что я хочу... наслаждаюсь.
$PWD
всегда имеет абсолютный путь к рабочему каталогу. Кроме того, find
не потерпит косых черт, поэтому вы не отвечаете на вопрос в том виде, в котором он был задан. Более быстрый способ сделать то, что вы хотите сделать, это просто echo "$PWD/$1"
Для каталогов dirname
происходит сбой для ../
и возвращает ./
.
функция nolan6000 может быть изменена, чтобы исправить это:
get_abs_filename() {
# $1 : relative filename
if [ -d "${1%/*}" ]; then
echo "$(cd ${1%/*}; pwd)/${1##*/}"
fi
}
Ответ dogbane
с описанием того, что происходит:
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
Пояснение:
"$1"
dirname "$1"
cd "$(dirname "$1")
в этот относительный dir и получаем для него абсолютный путь, запустив pwd
команду оболочки$(basename "$1")
echo
itАльтернатива для получения абсолютного пути в Ruby:
realpath() {ruby -e "require 'Pathname'; puts Pathname.new('$1').realpath.to_s";}
Работает без аргументов (текущая папка) и относительного и абсолютного пути к файлам или папкам в качестве агимента.
Это не ответ на вопрос, но для тех, кто выполняет скриптинг:
echo `cd "$1" 2>/dev/null&&pwd||(cd "$(dirname "$1")";pwd|sed "s|/*\$|/${1##*/}|")`
он правильно обрабатывает/.../и т.д. Я также работаю над OSX
#! /bin/bash
file="$@"
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.
realpath "foo bar"
-> /home/myname/foo bar
. Если вы не можете взять в кавычки аргументы командной строки, это не realpath
.
Эй, ребята, я знаю, что это старая нить, но я просто размещаю это для ссылки на кого-нибудь другого, кто посетил это, как я. Если я правильно понял вопрос, я думаю, что команда locate $filename
. Он отображает абсолютный путь к предоставленному файлу, но только если он существует.
locate
- это утилита для поиска файлов / путей по имени. Он может выполнять эту работу, но также может находить другие совпадения и может не находить существующий файл, если сначала не updatedb
как root.