Как узнать имя файла сценария в сценарии Bash?
Как я могу определить имя файла сценария Bash внутри самого сценария?
например, если мой скрипт находится в файле runme.sh
, то как бы я сделал это, чтобы отобразить "вы работаете runme.sh-сообщение без жесткого кодирования?
21 ответов
me=`basename ""`
для чтения через символическую ссылку, которая обычно не то, что вы хотите (вы обычно не хотите путать пользователя таким образом), попробуйте:
me="$(basename "$(test -L "" && readlink "" || echo "")")"
IMO, это приведет к путанице. "Я побежал foo.sh но он говорит, что я бегу bar.sh!? Должна быть ошибка!"Кроме того, одна из целей иметь по-разному названные символические ссылки-обеспечить различную функциональность на основе имени, которое она называется (думаю, gzip и gunzip на некоторых платформах).
# ------------- SCRIPT ------------- #
#!/bin/bash
echo
echo "# arguments called with ----> ${@} "
echo "# $1 ----------------------> "
echo "# $2 ----------------------> "
echo "# path to me ---------------> "
echo "# parent path --------------> ${0%/*} "
echo "# my name ------------------> ${0##*/} "
echo
exit
# ------------- CALLED ------------- #
# Notice on the next line, the first argument is called within double,
# and single quotes, since it contains two words
$ /misc/shell_scripts/check_root/show_parms.sh "'hello there'" "'william'"
# ------------- RESULTS ------------- #
# arguments called with ---> 'hello there' 'william'
# ----------------------> 'hello there'
# ----------------------> 'william'
# path to me --------------> /misc/shell_scripts/check_root/show_parms.sh
# parent path -------------> /misc/shell_scripts/check_root
# my name -----------------> show_parms.sh
# ------------- END ------------- #
С bash > = 3 следующие работы:
$ ./s
0 is: ./s
BASH_SOURCE is: ./s
$ . ./s
0 is: bash
BASH_SOURCE is: ./s
$ cat s
#!/bin/bash
printf ' is: %s\n$BASH_SOURCE is: %s\n' "" "$BASH_SOURCE"
Если в имени скрипта есть пробелы, более надежный способ-использовать ""
или "$(basename "")"
- или на MacOS:"$(basename \"\")"
. Это предотвращает искажение или интерпретацию имени каким-либо образом. В общем, хорошей практикой всегда является двойное цитирование имен переменных в оболочке.
$BASH_SOURCE
дает правильный ответ при поиске сценария.
это, однако, включает путь, чтобы получить только имя файла скриптов, используйте:
$(basename $BASH_SOURCE)
ответ Крис Конвей, в Linux (по крайней мере) вы бы сделали это:
echo $(basename $(readlink -nf ))
readlink выводит значение символьной ссылки. Если это не символическая ссылка, она печатает имя файла. - n говорит ему не печатать новую строку. - f говорит ему полностью следовать по ссылке (если символическая ссылка была ссылкой на другую ссылку, она также разрешит эту ссылку).
я обнаружил, что эта строка всегда работает, независимо от того, является ли файл источником или запускается как скрипт.
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
если вы хотите следовать символическим ссылкам, используйте readlink
на пути, который вы получаете выше, рекурсивно или нерекурсивно.
причина работы ОДН-вкладыша объяснена пользой BASH_SOURCE
переменная окружения и ее ассоциат FUNCNAME
.
BASH_SOURCE
переменная массива, члены которой являются источником имена файлов, в которых определены соответствующие имена функций оболочки в переменной массива FUNCNAME. Функция оболочки ${FUNCNAME[$i]} определяется в файле ${BASH_SOURCE[$i]} и вызывается из ${BASH_SOURCE[$i+1]}.
FUNCNAME
переменная массива, содержащая имена всех функций оболочки, находящихся в настоящее время в стеке вызовов выполнения. Элемент с индексом 0-это имя любой выполняемой в данный момент функции оболочки. Самый нижний элемент (с высокий индекс) является "основным". Эта переменная существует только при выполнении функции оболочки. Назначения FUNCNAME не имеют никакого эффекта и возвращают состояние ошибки. Если FUNCNAME не установлен, он теряет свои специальные свойства, даже если он впоследствии сбрасывается.
эта переменная может использоваться с BASH_LINENO и BASH_SOURCE. Каждый элемент FUNCNAME имеет соответствующие элементы в BASH_LINENO и BASH_SOURCE для описания стека вызовов. Например, ${FUNCNAME[$i]} был вызван из файла ${BASH_SOURCE[$i+1]} под номером строки ${BASH_LINENO[$i]}. Вызывающий объект builtin отображает текущий стек вызовов, используя эту информацию.
[источник: руководство bash]
эти ответы верны для случаев, которые они указывают, но есть еще проблема, если вы запустите сценарий из другого сценария с помощью ключевого слова "source" (так что он работает в той же оболочке). В этом случае, вы получаете $0 вызывающего скрипта. И в этом случае я не думаю, что можно получить название самого скрипта.
Это крайний случай и не следует воспринимать слишком серьезно. Если вы запустите скрипт из другого скрипта (без источника), используя $0 будет работа.
Re: (принятый) ответ Танктала выше, немного более чистый способ использовать:
me=$(readlink --canonicalize --no-newline )
Если ваш сценарий был получен из другого сценария bash, вы можете использовать:
me=$(readlink --canonicalize --no-newline $BASH_SOURCE)
Я согласен, что было бы запутанно разыменовать символические ссылки, если ваша цель-предоставить обратную связь пользователю, но есть случаи, когда вам нужно получить каноническое имя скрипта или другого файла, и это лучший способ, imo.
если вызвать скрипт как
/home/mike/runme.sh
$0-это полное имя
/home/mike/runme.sh
basename $0 получит имя базового файла
runme.sh
и нужно поставить это имя в переменную типа
filename=$(basename )
и добавить дополнительный текст
echo "You are running $filename"
так что ваши скрипты как
/home/mike/runme.sh
#!/bin/bash
filename=$(basename )
echo "You are running $filename"
вы можете использовать $0 для определения имени скрипта (с полным путем) - чтобы получить имя скрипта, только вы можете обрезать эту переменную с
basename
this="$(dirname "$(realpath "$BASH_SOURCE")")"
это разрешает символические ссылки (realpath делает это), обрабатывает пробелы (двойные кавычки делают это) и найдет текущее имя скрипта даже при источнике (. ./ myscript) или вызывается другими скриптами ($BASH_SOURCE обрабатывает это). После всего этого хорошо сохранить это в переменной среды для повторного использования или для легкой копии в другом месте (this=)...
поскольку некоторые комментарии спрашивали о имени файла без расширения, вот пример того, как это сделать:
FileName=${0##*/}
FileNameWithoutExtension=${FileName%.*}
наслаждайтесь!
информация благодаря Биллу Эрнандесу. Я добавил некоторые предпочтения, которые я принимаю.
#!/bin/bash
function Usage(){
echo " Usage: show_parameters [ arg1 ][ arg2 ]"
}
[[ ${#2} -eq 0 ]] && Usage || {
echo
echo "# arguments called with ----> ${@} "
echo "# $1 -----------------------> "
echo "# $2 -----------------------> "
echo "# path to me ---------------> " | sed "s/$USER/$USER/g"
echo "# parent path --------------> ${0%/*} " | sed "s/$USER/$USER/g"
echo "# my name ------------------> ${0##*/} "
echo
}
Ура
на bash
вы можете получить имя файла сценария, используя . Вообще
,
etc для доступа к аргументам CLI. Аналогично
- это доступ к имени, которое запускает скрипт (имя файла скрипта).
#!/bin/bash
echo "You are running "
...
...
если вы вызываете скрипт с path like /path/to/script.sh
затем также даст имя файла с путем. В этом случае нужно использовать
$(basename )
чтобы получить только имя файла сценария.
echo "$(basename "`test -L ${BASH_SOURCE[0]} \
&& readlink ${BASH_SOURCE[0]} \
|| echo ${BASH_SOURCE[0]}`")"
не отвечает на вопрос (как я его понимаю). Демонстрация:
$ cat script.sh #! /bin/sh echo `basename ` $ ./script.sh script.sh $ ln script.sh linktoscript $ ./linktoscript linktoscript
как сделать ./linktoscript
распечатать script.sh
?
[EDIT] Per @ephemient в комментариях выше, хотя символическая ссылка может показаться надуманной, можно поиграть с такой, что он не представляет ресурс файловой системы. Операция немного двусмысленна о том, чего он хотел.
DIRECTORY=$(cd `dirname ` && pwd)
Я получил выше от другого вопроса переполнения стека,может ли скрипт Bash сказать, в каком каталоге он хранится?, но я думаю, что это полезно и для этой темы.
что-то вроде этого?
export LC_ALL=en_US.UTF-8
#!/bin/bash
#!/bin/sh
#----------------------------------------------------------------------
start_trash(){
ver="htrash.sh v0.0.4"
$TRASH_DIR # url to trash $MY_USER
$TRASH_SIZE # Show Trash Folder Size
echo "Would you like to empty Trash [y/n]?"
read ans
if [ $ans = y -o $ans = Y -o $ans = yes -o $ans = Yes -o $ans = YES ]
then
echo "'yes'"
cd $TRASH_DIR && $EMPTY_TRASH
fi
if [ $ans = n -o $ans = N -o $ans = no -o $ans = No -o $ans = NO ]
then
echo "'no'"
fi
return $TRUE
}
#-----------------------------------------------------------------------
start_help(){
echo "HELP COMMANDS-----------------------------"
echo "htest www open a homepage "
echo "htest trash empty trash "
return $TRUE
} #end Help
#-----------------------------------------------#
homepage=""
return $TRUE
} #end cpdebtemp
# -Case start
# if no command line arg given
# set val to Unknown
if [ -z ]
then
val="*** Unknown ***"
elif [ -n ]
then
# otherwise make first arg as val
val=
fi
# use case statement to make decision for rental
case $val in
"trash") start_trash ;;
"help") start_help ;;
"www") firefox $homepage ;;
*) echo "Sorry, I can not get a $val for you!";;
esac
# Case stop