Как получить абсолютный каталог файла в bash?
Я написал bash script, который принимает входной файл в качестве аргумента и читает его.
Этот файл содержит некоторые пути (относительно его расположения) к дополнительным файлам.
Я хотел бы, чтобы script перешел в папку, содержащую входной файл, для выполнения дальнейших команд.
Итак, как я могу получить папку (и только папку) из входного файла? (В linux.)
Ответы
Ответ 1
Чтобы получить полный путь, используйте:
readlink -f relative/path/to/file
Чтобы получить каталог файла:
dirname relative/path/to/file
Вы также можете объединить два:
dirname $(readlink -f relative/path/to/file)
Если readlink -f
недоступен в вашей системе, вы можете использовать это *:
function myreadlink() {
(
cd "$(dirname $1)" # or cd "${1%/*}"
echo "$PWD/$(basename $1)" # or echo "$PWD/${1##*/}"
)
}
Обратите внимание, что если вам нужно только перейти в каталог файла, указанного как относительный путь, вам не нужно знать абсолютный путь, относительный путь совершенно допустим, поэтому просто используйте:
cd $(dirname relative/path/to/file)
если вы хотите вернуться (пока скрипт работает) к исходному пути, используйте pushd
вместо cd
и popd
когда вы закончите.
* Несмотря на то, что myreadlink
выше достаточно хорош в контексте этого вопроса, он имеет некоторые ограничения относительно инструмента readlink
, предложенного выше. Например, он не правильно следует по ссылке на файл с другим basename
.
Ответ 2
Взгляните на страницу руководства для realpath
, я использую это и что-то вроде:
CONTAININGDIR = $(realpath ${FILEPATH%/*})
чтобы сделать то, что звучит так, как вы пытаетесь сделать.
Ответ 3
Это будет работать как для файла, так и для папки:
absPath(){
if [[ -d "$1" ]]; then
cd "$1"
echo "$(pwd -P)"
else
cd "$(dirname "$1")"
echo "$(pwd -P)/$(basename "$1")"
fi
}
Ответ 4
$cat abs.sh
#!/bin/bash
echo "$(cd "$(dirname "$1")"; pwd -P)"
Некоторые объяснения:
- Этот script получает относительный путь как аргумент
"$1"
- Затем мы получаем часть dirname этого пути (вы можете передать либо dir или файл в этот script):
dirname "$1"
- Тогда we
cd "$(dirname "$1");
в этот относительный dir
-
pwd -P
и получить абсолютный путь. Опция -P
позволяет избежать символических ссылок
- В качестве последнего шага мы
echo
it
Затем запустите свой script:
abs.sh your_file.txt
Ответ 5
Попробуйте наш новый Bash библиотечный продукт realpath-lib в GitHub, который мы предоставили сообществу бесплатно и без использования. Он чист, прост и хорошо документирован, так что это здорово учиться. Вы можете сделать:
get_realpath <absolute|relative|symlink|local file path>
Эта функция является ядром библиотеки:
if [[ -f "$1" ]]
then
# file *must* exist
if cd "$(echo "${1%/*}")" &>/dev/null
then
# file *may* not be local
# exception is ./file.ext
# try 'cd .; cd -;' *works!*
local tmppwd="$PWD"
cd - &>/dev/null
else
# file *must* be local
local tmppwd="$PWD"
fi
else
# file *cannot* exist
return 1 # failure
fi
# reassemble realpath
echo "$tmppwd"/"${1##*/}"
return 0 # success
}
Он Bash 4+, не требует каких-либо зависимостей, а также предоставляет get_dirname, get_filename, get_stemname и validate_path.
Ответ 6
Проблема с приведенным выше ответом идет с файлами ввода с "./" как "./my-file.txt"
Обходной путь (многих):
myfile="./somefile.txt"
FOLDER="$(dirname $(readlink -f "${ARG}"))"
echo ${FOLDER}
Ответ 7
Я использую readlink -f работает над linux
так
FULL_PATH=$(readlink -f filename)
DIR=$(dirname $FULL_PATH)
PWD=$(pwd)
cd $DIR
#<do more work>
cd $PWD