Я думаю, что ответ НЕТ.
Если я правильно понял, вам нужно создать переменную user_entry
, чтобы вы могли написать:
echo "try '$user_entry -s $@' instead"
Я расскажу о том, почему я думаю, что вы не можете ниже, но сначала давайте попробуем понять поведение. Вкратце, $0
- это команда, данная субоболочке, которая выполняет сценарий.
Причина того, что вы описываете как происходящее , происходит , состоит в том, что выполнение скрипта запускает скрипт в под-оболочке. В этой под-оболочке аргументы, которые становятся $0
, $1
, $2
, разрешаются и завершаются. Чтобы увидеть это, попробуйте следующее. Вот программа, которую я написал, которая покажет концепции, которые, я надеюсь, объяснят вещи. (Это также позаботится о «дополнительном флаге», который вы описываете.)
Перейдите в каталог, который НЕ находится в вашем PATH
, и сохраните следующую программу. Я назвал это try_it.sh
#/bin/bash
echo "Welcome to the program!"
#print out all of the arguments as given in the subshell
for (( i=0;i<=$#;i++ )); do
echo "Argument ${i} is: ${!i}"
# bash's inderection feature, allows $0, $1, $2, ...
done #endof: for (( i=0;i<=$#;i++ ))
if [[ $1 != "-s" ]] ; then
echo "try '$0 -s $@' instead"
fi #endof: if [[ $1 != "-s" ]]
echo "Working directory: $(pwd)"
echo '$'"0 = $0"
echo "Everything before the script name and last / : "\
'${'"0"'%/*}'" = "${0%/*}
echo "Just the script name: "'${'"0"'##*/}'" = "${0##*/}
while true; do
echo "Hit Ctrl+C to stop this program's execution."
sleep 10000 # infinite loop, with instructions on how to get out
done #endof: while true
Запустите chmod +x try_it.sh
, чтобы убедиться, что он исполняемый.
Теперь, если возможно (это будет намного легче увидеть), закройте все оболочки (клеммы).
Откройте новый терминал (назовем его Terminal1) и введите ps
. Я надеюсь, что имеет смысл написать следующее как еще один способ описания точно такого же действия:
Terminal1> ps
Этот ps
сообщает вам, какие процессы выполняются в ядре Linux. Вы должны увидеть один bash
и один ps
на выходе. 1 bash
в выходных данных говорит о том, что 1 оболочка открыта, что, я надеюсь, вы увидите на своем экране.
Откройте второй терминал, назовем его Terminal2.
Вернитесь к терминалу 1 и введите
Terminal1> ps
Теперь вы должны увидеть два bash
s и один ps
на выходе. (Могут быть и другие вещи, но есть не более двух bash
с и не меньше.) 2 bash
с сообщают, что открыты 2 оболочки, которые, я надеюсь, вы увидите на своем экране.
Хорошо. Давайте разберемся с процессом $0
. Я не собираюсь выкладывать здесь весь вывод. Надеюсь, увидев вывод на вашем экране (как вы пытаетесь запустить скрипт, как описано,) вы можете выяснить, как создать переменную user_entry
. На самом деле я не думаю, что вы можете сделать это, но я постараюсь дать вам знать, что происходит.
Пойдем в Терминал2. Перейдите в каталог, в котором находится скрипт try_it.sh
.
Terminal2> cd /path/to/script/
Запустите скрипт (в Terminal2) как
Terminal2> ./try_it.sh 1 2 3
Вот что я увидел:
$ ./try_it.sh 1 2 3
Welcome to the program!
Argument 0 is: ./try_it.sh
Argument 1 is: 1
Argument 2 is: 2
Argument 3 is: 3
try './try_it.sh -s 1 2 3' instead
Working directory: /home/me/other_dir
$0 = ./try_it.sh
Everything before the script name and last / : ${0%/*} = .
Just the script name: ${0##*/} = try_it.sh
Hit Ctrl+C to stop this program's execution.
( Пока что не нажимайте "Ctrl + C". ) Обратите внимание, что мой /path/to/script/
равен /home/me/other_dir/
Вернитесь в Terminal1 и снова запустите ps
.
Terminal1> ps
Вы должны увидеть 3 bash
с. У вас есть 2 открытых снаряда и один субоболочка. Обратите внимание, что бесконечный цикл позволяет вам «увидеть» вложенную оболочку. Кроме того, sleep
, который вы видите в выводе ps
, сохраняет «Ctrl + C, чтобы остановить выполнение этой программы». от повторения на экране.
Здесь мы можем видеть, что команда, «переданная» суб-оболочке, была ./try_it.sh
. $0
- команда, данная субоболочке.
Хорошо, Ctrl+C
на Терминале2. Идем дальше и ps
на Терминале1.
Terminal1> ps
Только 2 bash
с. Подоболочка была закрыта.
Теперь попробуйте следующее:
Terminal2> /path/to/script/try_it.sh 1 2 3
Terminal1> ps
Количество bash
с: 3; команда, передаваемая суб-оболочке: /path/to/script/try_it.sh
Попробуйте это:
Terminal2> try_it.sh 1 2 3
Вы получаете ошибку. Если путь к исполняемому файлу не был добавлен в PATH
, для его выполнения необходим относительный или абсолютный путь к сценарию.
Давайте поместим наш скрипт в PATH
. Для меня (на Cygwin) это следующая команда. Убедитесь, что вы знаете, как правильно добавить PATH
в вашей системе. Не используйте это без проверки!
export PATH="$(pwd):$PATH"
Не волнуйтесь, это исчезнет с вашего пути в следующий раз, когда вы закроете Терминал 2.
Теперь, пока вы все еще в /path/to/script
, запустите
Terminal2> try_it.sh
Terminal1> ps
Количество bash
с: 3; команда, передаваемая суб-оболочке: /path/to/script/try_it.sh
"Магия Linux" прошла через каталоги в PATH
, ища тот, в котором был исполняемый файл try_it.sh
. Волшебство Linux соединяет правильный каталог и имя сценария, а затем передает эту полную команду суб-оболочке.
Давайте создадим еще один каталог в /path/to/script/
Terminal2> mkdir another_directory
Terminal2> cd another_directory
Давайте запустим его с относительным путем.
Terminal2> ../try_it.sh 1 2 3
Terminal1> ps
Количество bash
с: 3; команда, передаваемая суб-оболочке: ../try_it.sh
Безумный относительный путь. Мой /path/to/script/
был действительно /home/me/other_dir/
, поэтому я пройду сумасшедший относительный путь следующим образом, отметив, что я нахожусь в каталоге another_directory
.
Terminal2> ../../other_dir/another_directory/../try_it.sh 1 2 3
Terminal1> ps
Количество bash
с: 3; команда, передаваемая суб-оболочке: ../../other_dir/another_directory/../try_it.sh
Мы поместили путь скрипта в PATH
, поэтому давайте попробуем следующее из another_directory
Terminal2> try_it.sh
Terminal1> ps
Количество bash
с: 3; команда, передаваемая суб-оболочке: /path/to/script/try_it.sh
Теперь абсолютный путь. Это от another_directory
Terminal2> /path/to/script/try_it.sh 1 2 3
Terminal1> ps
Количество bash
с: 3; команда, передаваемая суб-оболочке: /path/to/script/try_it.sh
Еще раз, $0
- команда, данная субоболочке.
<Ч />
Мои мысли относительно ответа на ваш вопрос
Вы спросили,
Есть ли способ узнать, какой именно текст набрал пользователь для команды, запустившей файл скрипта?
Я думаю, что ответ - нет. Если вы пройдете шаги, которые я показал, я надеюсь, вы немного поймете, почему вы так поступили. Я думаю, что в большинстве случаев вы можете узнать, что набрал пользователь. Однако я не вижу способа провести различие между этими двумя командами (однажды /path/to/script
был добавлен к вашему PATH
)
Terminal2> try_it.sh 1 2 3
и
Terminal2> /path/to/script/try_it.sh 1 2 3
Может быть, вы сможете найти способ определить разницу. Если так, опубликуйте это как ответ.
<Ч />
Примечание : См. этот пост SO и эту ссылку (поиск "Удаление подстроки"), чтобы получить пояснения по ${#%/*}
и ${##*/}
. Спасибо тем людям за то, что они сделали это, поэтому мне не нужно писать объяснение.
<Ч />
Просто для удовольствия
Давайте посмотрим, действительно ли я запрограммировал правильное поведение, когда кто-то использует флаг -s
.
$ /path/to/script/try_it.sh -s 1 2 3
Welcome to the program!
Argument 0 is: /home/dblack/other_dir/try_it.sh
Argument 1 is: -s
Argument 2 is: 1
Argument 3 is: 2
Argument 4 is: 3
Working directory: /home/dblack/other_dir
$0 = /home/dblack/other_dir/try_it.sh
Everything before the script name and last / : ${0%/*} = /home/dblack/other_dir
Just the script name: ${0##*/} = try_it.sh
Hit Ctrl+C to stop this program's execution.
Это сработало. Ура!