Полный путь к сценарию TCSH

В оболочке bash я могу получить полный путь к скрипту, даже если скрипт вызывается по источнику, ссылке, ./... и т. д. Эти волшебные строки bash:

 #Next lines just find the path of the file.
 #Works for all scenarios including:
 #when called via multiple soft links.
 #when script called by command "source" aka . (dot) operator.
 #when arg $0 is modified from caller.
 #"./script" "/full/path/to/script" "/some/path/../../another/path/script" "./some/folder/script"
 #SCRIPT_PATH is given in full path, no matter how it is called.
 #Just make sure you locate this at start of the script.
 SCRIPT_PATH="${BASH_SOURCE[0]}";
 if [ -h "${SCRIPT_PATH}" ]; then
   while [ -h "${SCRIPT_PATH}" ]; do SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done
 fi
 pushd `dirname ${SCRIPT_PATH}` > /dev/null
 SCRIPT_PATH=`pwd`;
 popd  > /dev/null

Как получить путь к скрипту при тех же условиях в оболочке TCSH? Что это за «волшебные линии»?

P.S. Это не дубликат этот и подобные вопросы. Я знаю о $0.


person MajesticRa    schedule 23.08.2011    source источник
comment
Я абсолютно согласен с вами. Но моя цель — сделать жизнь пользователей максимально легкой. И им было бы легко, если бы они могли просто запускать исходный файл environment.csh из любого места, где они хотят. Требование TCSH связано с тем, что RHEL 6 использует его в качестве оболочки по умолчанию для пользователей.   -  person MajesticRa    schedule 23.08.2011
comment
Если вы используете tsch только потому, что это оболочка по умолчанию, почему бы не изменить оболочку по умолчанию?   -  person carlpett    schedule 23.08.2011
comment
Поскольку это не МОЯ оболочка по умолчанию, это оболочка ПОЛЬЗОВАТЕЛЕЙ по умолчанию. Разве вы не слышали, что иногда что-то разрабатывается для пользователей?..   -  person MajesticRa    schedule 23.08.2011
comment
Если скрипт вызывается с текущим каталогом /home/user1 с использованием имени /usr/local/bin/xyz, но это символическая ссылка, содержащая ../libexec/someprog/executable, то фрагмент кода выдаст неправильный ответ (скорее всего, он скажет /home/user1, потому что /home/libexec/someprog/executable не существует). Оборачивать цикл while в if бессмысленно; код должен просто содержать цикл while. Вы должны найти функцию realpath(); может быть даже команда, использующая его, уже доступная. Конечно, несложно написать команду, которая использует realpath().   -  person Jonathan Leffler    schedule 23.08.2011
comment
Я не спрашиваю об этом сценарии. Спрашиваю про ТСШ. Если вы такой ГУРУ, может быть, вам лучше дать решение?   -  person MajesticRa    schedule 23.08.2011
comment
@MajesticRa: Во-первых, возможно, это не имелось в виду, но я прочитал ваш тон в последних двух комментариях как довольно агрессивный. Пожалуйста, учтите это в будущих комментариях. Возвращаясь к вопросу, я имел в виду изменение оболочки по умолчанию для пользователей. Чтобы изменить для существующих пользователей, а не только для будущих, вы можете перебрать всех пользователей и usermod использовать их, например, bash.   -  person carlpett    schedule 23.08.2011
comment
Мои комментарии не агрессивны, они раздражительны. Раздражают лица, которым, похоже, нечего делать, кроме как оставлять глупые помойные ремарки.   -  person MajesticRa    schedule 24.08.2011


Ответы (2)


Я не использую tcsh и не претендую на статус гуру в нем или любом другом варианте оболочки C. Я также твердо верю, что программирование на Csh считается вредным содержит много правды. ; Я использую оболочку Korn или Bash.

Однако я могу просмотреть справочные страницы и использовал справочную страницу для tcsh (tcsh 6.17.00 (Astron) 2009-07-10 (x86_64-apple-darwin) в MacOS 10.7.1 Lion).

Насколько я вижу, аналога переменной ${BASH_SOURCE[0]} в tcsh нет, поэтому отправная точка для фрагмента скрипта в вопросе отсутствует. Таким образом, если я что-то не упустил в руководстве или оно неполное, нет простого способа добиться такого же результата в tcsh.

У исходного фрагмента сценария тоже есть некоторые проблемы, как отмечено в комментариях. Если скрипт вызывается с текущим каталогом /home/user1 с использованием имени /usr/local/bin/xyz, но это символическая ссылка, содержащая ../libexec/someprog/executable, то фрагмент кода выдаст неправильный ответ (скорее всего, он скажет /home/user1, потому что каталог /home/libexec/someprog не существует).

Кроме того, оборачивать цикл while в цикл if бессмысленно; код должен просто содержать цикл while.

SCRIPT_PATH="${BASH_SOURCE[0]}";
while [ -h "${SCRIPT_PATH}" ]; do SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done

Вы должны найти функцию realpath(); может быть даже команда, использующая его, уже доступная. Конечно, несложно написать команду, которая использует realpath(). Однако, насколько я могу судить, ни одна из стандартных команд Linux не оборачивает функцию realpath(), что очень жаль, так как это помогло бы вам решить проблему. (Конкретно команды stat и readlink не помогают.)

В самом простом случае вы могли бы написать программу, использующую realpath(), следующим образом:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main(int argc, char **argv)
{
    int rc = EXIT_SUCCESS;
    for (int i = 1; i < argc; i++)
    {
        char *rn = realpath(argv[i], 0);
        if (rn != 0)
        {
            printf("%s\n", rn);
            free(rn);
        }
        else
        {
            fprintf(stderr, "%s: failed to resolve the path for %s\n%d: %s\n",
                    argv[0], argv[i], errno, strerror(errno));
            rc = EXIT_FAILURE;
        }
    }
    return(rc);
}

Если эта программа называется realpath, то фрагмент сценария Bash сводится к следующему:

SCRIPT_PATH=$(realpath ${BASH_SOURCE[0]})
person Jonathan Leffler    schedule 24.08.2011

ЕСЛИ ваш скрипт csh называется test.csh, то это будет работать:

/usr/sbin/lsof +p $$ | \grep -oE /.\*test.csh

person engtech    schedule 29.04.2013
comment
Я почти отклонил это как слишком рискованное из-за того, что слишком много работал над перечислением всех открытых файлов, но на практике я обнаружил, что у моего обычного пользователя не слишком много открытых файлов, и поиск setup.csh достаточно ограничен. Это некрасиво, но единственное решение, которое я нашел для тех из моих упрямых пользователей, которые отказываются идти в ногу со временем и переключаются на bash. - person Karl Horton; 17.10.2018