команда realpath не найдена

24

У меня есть Debian Squeeze AMD64. Моя текущая оболочка bash. Если я пишу следующее в моем терминале, это работает:

$ uname -a
Linux core 2.6.32-5-amd64 #1 SMP Fri May 10 08:43:19 UTC 2013 x86_64 GNU/Linux
$ echo $SHELL
/bin/bash                                                                                                                                                                                     
$ echo $(realpath test.sh)                                                                                                                                                     
/home/ffortier/test.sh

Мой файл test.sh выглядит так:

#!/bin/bash
echo $(realpath "$1")

Если я пытаюсь выполнить следующее, я получаю ошибку

$ ./test.sh test.sh 
./test.sh: line 2: realpath: command not found

Как я могу использовать команду realpath в файле bash?

Дополнительная информация

$ type -a realpath
realpath is a function                                                                                                                                                                        
realpath ()                                                                                                                                                                                   
{                                                                                                                                                                                             
    f=$@;                                                                                                                                                                                     
    if [ -d "$f" ]; then                                                                                                                                                                      
        base="";                                                                                                                                                                              
        dir="$f";                                                                                                                                                                             
    else                                                                                                                                                                                      
        base="/$(basename "$f")";                                                                                                                                                             
        dir=$(dirname "$f");                                                                                                                                                                  
    fi;                                                                                                                                                                                       
    dir=$(cd "$dir" && /bin/pwd);                                                                                                                                                             
    echo "$dir$base"                                                                                                                                                                          
}           
Фрэнсис
источник

Ответы:

9

Является ли realpath реальной командой или скриптом? Я бы проверил, откуда это.

$ type -a realpath

Я не знаком с этим инструментом, и поэтому он, вероятно, не является частью вашего обычного дистрибутива, возможно, он установлен в нестандартном месте, которого нет в Bash, $PATHно в вашей среде входа в систему $PATH.

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

echo $(/path/to/realpath test.sh)

Или измените ваш скрипт $PATHтак, чтобы он также включал это нестандартное местоположение.

Функции в оболочке

Большая часть вашей среды не вызывается, когда вы вызываете сценарий оболочки. Если вы думаете об этом, это имеет большой смысл, поскольку вы, как правило, не хотите, чтобы в сценариях был весь дополнительный багаж, который может иметь среда пользователя.

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

#!/bin/bash -l
echo $(realpath "$1")
SLM
источник
Это функция, см. Редактирование
Фрэнсис
@Francis - да, функции не включены, когда вы вызываете свой скрипт. Вам нужно будет найти их, если вы хотите, чтобы они пришли вместе. Узнайте, какой файл предоставляет функцию, и отправьте ее. Если вы просто хотите, чтобы весь ваш env. затем измените ваш звонок на bash #!/bin/bash -l.
SLM
Как я могу найти, откуда эта функция?
Фрэнсис
1
@mikeserv - спасибо, когда я написал это, я все еще использовал Fedora 14, который не включал realpath. Моя система Fedora 19 теперь включает этот инструмент. Также обратите внимание, что OP использовал ядро ​​Debian w / 2.6, поэтому его система тоже не работала бы, realpathучитывая его возраст.
СЛМ
1
@mikeserv - да, я был удивлен, это старый вопрос Q, но информация о commandбыла все еще полезна для меня. Это более портативный способ сделать то, что я показывал в оболочках POSIX.
slm
27

Есть как минимум две программы realpath:

  • Старая программа из прошлого, когда GNU coreutils не включал readlink -f. Сейчас это устарело в пользу readlink -f, поэтому многие дистрибутивы перестали его переносить.
  • realpathПрограмма введена в GNU Coreutils 8.15. Это слишком старо, чтобы быть в Debian squeeze или даже wheezy; на момент написания Debian нестабильный также не поставляется . Эта программа очень близка к readlink -f.

По какой-то причине у вас есть функция оболочки, которая частично эмулирует поведение realpath. Эта эмуляция является частичной: если вы вызываете ее по символической ссылке, она не следует по символической ссылке.

Поскольку это функция оболочки, предположительно загруженная из или через .bashrcнее, она доступна только для кода, выполняемого в вашей интерактивной оболочке. Если вы хотите, чтобы он был доступен для других программ, предполагая, что вы работаете в Linux, создайте скрипт, который эмулирует realpath:

#!/bin/sh
readlink -f -- "$@"

(Это не эмулирует realpathредко используемые параметры командной строки.)

Жиль "ТАК - перестань быть злым"
источник
2
В git-репозитории coreutils я не могу найти никаких доказательств того, что coreutils realpathсчитает программу устаревшей или что она не создана по умолчанию. Таким образом, Debian должен удалить его.
Каз
@Kaz О, ну, чтобы усложнить ситуацию, недавно coreutils (8.15) представила realpathдвоичный файл, который близок, но не совсем идентичен readlink -f. Стабильная версия Debian 8.13. Debian нестабильный решил оставить прежнюю программу .
Жиль "ТАК - перестань быть злым"
Это не было , что в последнее время - это был Ян 2012 savannah.gnu.org/forum/forum.php?forum_id=7076
mikeserv
1
@mikeserv Слишком недавний выпуск для рассылки в вопросе (Debian squeeze). Даже слишком недавно для текущей стабильной версии Debian.
Жиль "ТАК - перестань быть злым"
Это немного страшно. Сколько лет их openssl?
mikeserv
8

Он работает только в оболочке, потому что файл сценария имеет другую область видимости и не имеет доступа к вашим локальным функциям и псевдонимам, определенным в ваших файлах rc . И realpathкоманда на самом деле не существует в вашей системе.

Так что либо установите realpathиз пакета, определите свою собственную функцию (как часть сценария, проверьте несколько примеров ), либо поставьте rc- файл в свой сценарий, где он определен (например . ~/.bashrc).


Вот шаги, чтобы установить, realpathесли это не присутствует:

  • Ubuntu: sudo apt-get install coreutils
  • OS X: brew install coreutils

Ubuntu & Debian

В Debian или Ubuntu кажется, что realpathдолжен быть установлен по умолчанию. Я проверил последний Debian 8 (Jessie), и он, кажется, coreutilsустановлен по умолчанию.

Протестировано с использованием свежих образов виртуальных машин:

$ vagrant init debian/jessie64 && vagrant up --provider virtualbox && vagrant ssh
$ vagrant init ubuntu/vivid64 && vagrant up --provider virtualbox && vagrant ssh

Тогда в ВМ:

$ type -a realpath
realpath is /usr/bin/realpath

Вместо этого realpathвы также можете использовать readlink -f file(или greadlink) предоставляемый coreutilsпакет.

kenorb
источник