Выполнить как .test, а не ./test

26

Предположим, я нахожусь в той же папке, что и исполняемый файл, мне нужно будет ввести это, чтобы выполнить его:

./file

Я бы предпочел не печатать /, потому что /мне сложно печатать.

Есть ли более простой способ выполнить файл? В идеале это простой синтаксис, такой как:

.file

или что-то еще, но проще, чем вставлять /туда персонажа.

Возможно, есть какой-то способ поместить что-то в /binкаталог или создать псевдоним для интерпретатора, чтобы я мог использовать:

p file
IMSoP
источник
9
Может быть, заменить / с другим ключом, используя xmodmap? Так что, по крайней мере, проще набирать
Парень
26
Как примечание, широко/ используется в Unix, в основном как разделитель каталогов. Возможно, вам лучше найти более простой способ напечатать его.
Хрилис - по забастовке -
7
@RossPresser Этот вопрос мало что значит с тех пор. и ./ в начале файла два совершенно разных значения по техническим причинам, которые должен знать любой новичок. /набрать текст несложно для подавляющего большинства людей, и если у ОП есть травма, которая мешает этому, им следует рассмотреть альтернативные раскладки клавиатуры, поскольку они не могут /полностью избежать их, находясь в терминале.
JFA
1
@JFA Большинство клавиатурных раскладок, используемых в континентальной Европе, а также в Южной Америке, используют /shift-7, который сравнительно сложно напечатать даже без травм.
nitro2k01
6
История изменений: « Почему нельзя просто настроить сетевой интерфейс для выполнения всех интернет-запросов через удаленный хост через ssh на порту 22. » ಠ_ಠ
Дерек 朕 會

Ответы:

35

Это может быть «рискованно», но вы могли бы просто иметь. в вашем ПУТИ.

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

HaloJones
источник
1
Не понимаю, насколько это «рискованно»: мой путь был таким еще задолго до Linux, и он никогда не вызывал ни малейших проблем.
jamesqf
21
@jamesqf Это рискованно, потому что, если вы перейдете cdв каталог, доступный для записи всем пользователям, и попытаетесь использовать команду, которой нет в вашем пути, вы можете выполнить (возможно, злонамеренный) исполняемый файл с тем же именем, которое кто-то написал по этому пути. Это намного хуже, если вы положили .в начале вашего пути. В этом случае вредоносный исполняемый файл с именем lsбудет выполнен, если вы попытаетесь вызвать lsэтот каталог.
bytesized
2
Пожалуйста, избегайте этого по причинам, указанным выше. Команда pбудет лучше.
Гвидо
11
@jamesqf Когда это «твоя» система, и только ты используешь ее, это не так уж плохо. Проблема возникает (и за многие годы споткнула многих администраторов Unix) в многопользовательской системе. С самого .начала PATHвсе, что нужно сделать злоумышленнику, это добавить поддельную lsкоманду в свой каталог и убедить администратора «посмотреть на что-то странное», и у него есть root-доступ.
TripeHound
1
Хорошее решение, хотя оно не сработает, если имя файла окажется таким test, как в заголовке вопроса (поскольку testон встроен в оболочку и, вероятно, уже существует где-то в вашем файле $PATH).
Йеллоантфил
71

.будет автоматически завершать./ (печатать .и нажимать Tab) по крайней мере в современных оболочках Bash, поэтому вам не нужно использовать сложное или небезопасное (например, PATHмодификационное) решение.

Если он не завершается автоматически, вам может потребоваться установить пакет «bash-complete».

l0b0
источник
Вы уверены? .имеет несколько кандидатов на завершение: .(текущий каталог), ..(родительский каталог), .команду (для которой bash предоставляет нестандартный псевдоним source) и все имеющиеся файлы точек. Возможно bash-completionпакет игнорирует это; Я нахожу это ужасно раздражающим (например, это делает невозможным заполнение табуляцией имен dir в makeкомандной строке и, как правило, ужасно с make-файлами, полными неявных правил), поэтому я всегда очищаю его.
R ..
3
Я попробовал, и да, он выполняет автозаполнение таким образом. Практически в каждом случае это то, чего хотел бы обычный пользователь: я не думаю, что когда-либо видел файл точек, который должен быть исполняемым, запуск чего-либо в подкаталоге гораздо более распространен, чем запуск чего-либо в родительском каталоге, и IMO это делает чертовски хорошая работа по поиску makeцелей.
10
С bash 3.2 он не заполняется автоматически. Может ли это быть новым в bash 4?
Calimo
2
@Calimo Скорее, новинка в последних версиях bash-complete. Это далеко от фундаментальных изменений.
10
42

или .. возможно, давая интерпретатору псевдоним в файле bashrc, а затем просто

   p  file

Можно написать такую ​​функцию:

p() {
 ./"$@"
}

в вашем ~/.bashrc. Тогда вы сможете бежать p app argumentsвместо ./app arguments. Это решение работает для исполняемых файлов любого типа, включая скрипты и двоичные файлы.

"$@"расширяется до надлежащим образом цитируемого списка аргументов, передаваемых функции (сохраняя все специальные символы из расширения glob или variable), и, как указал @Scott, bashдостаточно умен, ./чтобы присоединиться к первому из них, сохраняя остальные.

aitap
источник
Несмотря на то, что он менее распространен для запуска приложения под другой командой, например, strace -f p appдля просмотра системных вызовов или $(which time) p appдля определения продолжительности работы. pкак исполняемый скрипт будет работать лучше в этих двух конкретных примерах, которые я придумал. Ни одно из этих решений не может работать ldd p app, хотя ldd и отличается тем, что требует полного пути, возможно, по таким причинам.
sourcejedi
Да, замена p app argsс ./app argsтаким способом , который является невидимым для любого трубопровода потребует ввода оболочки через какое - то препроцессор и будет вызывать все виды удовольствия , когда замена происходит в незапланированном месте :)
aitap
1
В этом случае не должно быть никаких кавычек $@? В противном случае он просто передаст один большой аргумент программе.
Кролтан
7
@Kroltan № $@это массив. При раскрытии внутри "каждый параметр раскрывается в отдельное слово. $*ведет себя так, как вы думаете.
8bittree
3
Я считаю, что вы сделали это излишне сложным, и это p() { ./"$@"; }все, что вам нужно.
Скотт
11

Вы можете добавить .к своему $PATH, добавив, например, PATH=$PATH:.к вашему /etc/profile, таким образом, вы можете выполнить fileпросто написав file, если он не находится в какой-то другой папке в вашем пути (например /usr/bin/). Обратите внимание, что это, как правило, не очень хорошая идея.

Почему это плохо: скажем, вы находитесь в ситуации, когда вы не полностью доверяете содержимому каталога - вы скачали его откуда-то изворотливо и хотите исследовать его перед запуском, или вы системный администратор, помогающий некоторым пользователя, просматривая его домашний каталог и т. д. Вы хотите перечислить каталог, поэтому вы пытаетесь набрать ls, но, к сожалению, вы сделали опечатку и в итоге вместо этого набрали sl. Автор этого вредоносного каталога предвидел это и поместил в него скрипт оболочки с именем «sl», который запускает «rm -rf --no-preserve-root /» (или что-то более вредоносное, например, установка руткита).

(Спасибо @Muzer за объяснение)

PHK
источник
13
Хотя я искренне согласен, вероятно, это объясняет, почему это не очень хорошая идея.
ymbirtt
16
Почему это плохо: скажем, вы находитесь в ситуации, когда вы не полностью доверяете содержимому каталога - вы скачали его откуда-то изворотливо и хотите исследовать его перед запуском, или вы системный администратор, помогающий некоторым пользователя, просматривая его домашний каталог и т. д. Вы хотите перечислить каталог, поэтому вы пытаетесь набрать ls, но, к сожалению, вы сделали опечатку и в итоге вместо этого набрали sl. Автор этого вредоносного каталога предвидел это и поместил в него скрипт оболочки с именем «sl», который запускает «rm -rf --no-preserve-root /» (или что-то более вредоносное, например, установка руткита).
Музер
2
Стоит объяснить, что если текущий каталог находится в начале $ PATH, взломщик может просто переопределить ls или другие общие команды
Délisson Junio
@ Muzer Huuuge шляпы из фольги здесь.
Сомбреро Цыпленок
4
@GillBates Это та вещь, о которой вам следует опасаться, будучи системным администратором, имеющим дело с реальными и потенциально злонамеренными пользователями, или с кем-то, кто анализирует подозрительные архивы на жизнь. Если ни то, ни другое не применимо, я согласен с вами. Я все еще не думаю, что это хорошая привычка, потому что вы никогда не знаете, когда ваши обстоятельства изменятся, вы получаете одну из этих работ, и вы будете бесконечно проклинать себя за то, что научили себя полагаться на небезопасное поведение; )
Muzer
10

Вы можете позвонить переводчику, например,

bash test

В этом случае скрипт будет работать, даже если у него нет ни строки Шебанга (например #!/bin/bash), ни исполняемого бита. Вы должны будете знать правильный переводчик, чтобы запустить его также. Вы можете сначала прочитать строку shebang файла, чтобы убедиться, что вы вызываете правильный интерпретатор, например, если в строке shebang написано

#!/usr/bin/env python3

ты бы позвонил

python3 test
Занна
источник
7
интерпретатор просто интерпретирует код, они не будут запускать двоичные файлы
Mc Kernel
Этот ответ несколько логичен, поскольку, возможно, интерпретатору может быть дан псевдоним в файле bashrc.
5
@McKernel Хороший вопрос, он работает только при наличии интерпретатора, а не для скомпилированных исполняемых файлов
Zanna
2
есть интерпретатор для скомпилированных исполняемых файлов:/lib/ld.so
Дмитрий Кудрявцев
7

Насколько я знаю, нет способа достичь этого, если вы не включите файл в путь env, поэтому вы можете запустить его, просто набрав: file

.fileне будет работать, так как это другое имя файла. Это файл называется .fileи нет ./file.

Я чувствую, что слеш может быть трудно напечатать для вас, потому что не английский макет, может быть? В этом случае это также происходит со мной, поэтому я часто меняю раскладку клавиатуры на английский, нажимая Alt + Shift в Windows (я использую Linux из ssh)

Mc Kernel
источник
7

Люди предложили добавить .к PATH, что это опасно , потому что это создает риск того, что вы случайно запустить вредоносную программу посаженной в мировом перезаписываемом каталоге. Но, если у вас есть исполняемые программы в нескольких каталогах , которыми вы владеете и доступны для записи только вам, то это безопасно (достаточно безопасно?) Поставить эти директор (е) в PATH, добавляя строку

PATH=$PATH:~/dev/myprog1:~/dev/myprog2

в ваш ~/.bashrcфайл. Конечно, это означает, что вы можете запустить программу из одного из этих каталогов из любой точки файловой системы. Например, вы могли бы cd /etcи напечатать foo, и он будет работать ~/dev/myprog1/foo. Это имеет небольшой недостаток: вы не можете иметь программы с одинаковыми именами в более чем одном каталоге. В частности, если у вас есть программы, вызываемые foo в обоих ~/dev/myprog1и ~/dev/myprog2, вы не сможете запустить вторую, кроме как путем указания пути. Точно так же, если у вас есть ~/dev/myprog1/cat- но почему вы хотите?


Другой подход, если у вас есть всего несколько программ, с которыми вы делаете это, это определить для них псевдонимы:

alias gizmo='./gizmo'
alias gonzo='./gonzo'

Или вы можете назвать псевдонимы, .gizmoи .gonzo если вы найдете это более интуитивным.

На самом деле, это в некоторой степени та же угроза безопасности, что и .ваша PATH. Если злоумышленник может читать ваши .bashrcи видеть свои псевдонимы, то он может поставить под названием вредоносных программ gizmoи gonzoв случайных каталогах , в надежде , что вы будете запускать его. Лучше сделать так, чтобы они использовали абсолютные пути:

alias gizmo='~/dev/myprog1/gizmo'
alias gonzo='~/dev/myprog2/gonzo'

Кстати, вам следует избегать именования исполняемого файла test, потому что это встроенная команда оболочки, и вы можете запускать программу под этим именем только путем указания пути или другого трюка.

G-Man говорит: «Восстанови Монику»
источник
В качестве альтернативы вы можете сделать рецепт (если вы используете Makefiles) и сделать make gizmoили make gonzo.
17
Извините, но я не уверен, что понимаю, как это относится к вопросу или моему ответу. Вы предлагаете, чтобы OP создавал Makefileв каждом каталоге, чтобы действия для make gizmoзавершения выполнялись gizmo ? (1) Это выглядит как неуклюжий способ сделать то же самое, что и pфункция, предложенная в вопросе, первоначально реализованная aitap и уточненная Скоттом. (2) Можете ли вы передать аргументы таким образом? ISTM, что make gizmo arg1 arg2эквивалентно make gizmo; make arg1; make arg2.
G-Man говорит: «Восстановите Монику»
1
(1) Возможно, мое предположение неверно, но мне не ясно, OP хочет избегать использования ./в каждом каталоге . На мой взгляд, он что-то разрабатывает, и ему просто нужно ./fileчасто запускать созданную программу . Я действительно не могу придумать ни одного другого сценария, когда часто нужно запускать локальный файл, и если он не запускает его часто, он не стал бы задавать вопрос (он сказал, что трудно, не невозможно ) (2) на самом деле, но Вы можете передать аргументы в рецепте.
ihato
(1) Ну, я думаю, мы можем согласиться с тем, что мотивация ОП и сфера его вопроса неясны. (2) Спасибо за ссылку.
G-Man говорит: «Восстановите Монику»
3

Чтобы расширить ответ Занны о интерпретаторах (извините, нет комментариев для комментария): «интерпретатор» для собственных исполняемых файлов (также называемых двоичными файлами ELF) - это динамический загрузчик ( ld.so), но обычно он не понимает синтаксис, который вы хотите:

$ /usr/lib/ld-linux-x86-64.so.2 program
program: error while loading shared libraries: program: cannot open shared object file
$ /usr/lib/ld-linux-x86-64.so.2 ./program
<program is launched>

(кроме того, если вы не вставите символическую ссылку ld.soна свой путь, вам все равно придется писать /s)

bacondropped
источник
Это специфично для Linux, верно? Не могли бы вы объяснить это больше, почему это работает? Я думал, что (Linux) ядро ​​выполнит разбор и решит, запускать ли двоичный файл и как, для чего это нужно binfmt_misc.
phk
2
@phk Файл специфичен для Linux, но концепция динамического компоновщика / загрузчика - нет. Например, FreeBSD имеет свои собственные /libexec/ld-elf.so.1. В Linux это не так просто, как «решить, как запустить двоичный файл»: binfmt_miscобнаруживает формат файла по магическим числам (ELF, сценарий shebang, CIL). После этого binfmt_elfвызывается обработчик. Он анализирует заголовки и разделы ELF; .interpраздел содержит путь динамического загрузчика; этот загрузчик запускается ядром, выполняет перемещение и переходит на _start. В FreeBSD (не уверен в других) нет binfmt, но принцип +/- похож.
Бекондроп
1
@phk о том, почему это работает - ld.soне имеет .interpи является статически связанным, что означает, что ему не нужно, чтобы другой динамический компоновщик / загрузчик разрешал свои внешние символы и делал математику перемещения.
Бекондроп
ISTR Solaris также имеет нечто подобное.
G-Man говорит: «Восстановите Монику»
3

Если мы можем начать настройку

mkdir -p ~/.local/bin
cat > ~/.local/bin/x << 'EOF'
#!/bin/sh
N="$1"
shift
exec "./$N" "$@"
EOF
chmod a+x ~/.local/bin/x

Большинство современных дистрибутивов уже включают ~ / .local / bin в $ PATH (добавьте export PATH="$HOME/.local/bin:$PATH"в свой, ~/.profileесли ваш нет). Тогда вы можете использовать x fileдля запуска ./file.

Не пытайтесь определить .команду. Команда . scriptуже выполняется scriptв текущей оболочке. Это позволяет scriptопределять переменные среды для текущей оболочки.

sourcejedi
источник
3
Я думаю, что здесь может быть хорошее предложение, но нет никакого объяснения того, что из этого делает. Я мог бы решить это, но у неопытного пользователя не было бы никаких шансов.
IMSoP
Нет необходимости перекладывать 1 доллар. Просто exec "$@".
reinierpost
$ (ln -s /bin/ls my-ls && exec my-ls) # bash: exec: my-ls: not found
sourcejedi
(1) Нет необходимости shift $1; просто exec ./"$@". (2) Поскольку вы говорите о сценарии оболочки, советовать людям не определять .команду немного бессмысленно / вводить в заблуждение , поскольку невозможно создать файл с именем .. (Можно и очень нежелательно определять псевдоним или вызываемую функцию оболочки ..)
Скотт,
1

Если нам разрешено создавать вспомогательные скрипты, вы можете создать помощника, который добавит pwd в PATH, а затем запустите

. pathhelper    #adds pwd to path
file            #now it can be run without ./

Это позволяет избежать добавления "." к пути и загрязнению вашего .profile каждым путем, который вы в какой-то момент захотите запустить.

Мы можем продвинуться к этому подходу, сделав помощника, который запускает новую оболочку с измененной переменной PATH. Если он принимает каталог в качестве параметра (используя pwd по умолчанию), он будет функционировать как a, pushdкоторый редактирует путь. Возможно, вам следует помнить, что любые изменения в других переменных среды будут потеряны при выходе из подоболочки, но в долго работающей оболочке переменная PATH не будет загромождена. В зависимости от ваших рабочих процессов это может быть выгодно.

:outer shell prompt$; subshellpathhelper    # launches a subshell with modified PATH
: subshell prompt $ ; file                  # in the subshell it can be run without ./

Но я думаю , если вы хотите работать с ним можно взломать pushdи popdпоэтому они могут сделать те же изменения в пути , не без подоболочку , который потеряет другие изменения.

pushd --path ~/some/path/    # normal pushd plus adds target to path
file                         # it can be run without ./ until you popd

(Вы не можете сделать то же самое, cdпотому что у него нет аналога popd.)

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

ShadSterling
источник
На самом деле, вы можете сделать что-то подобное cd, но это еще не все: создайте файл как .dircmdsи взломайте, cdчтобы сделать команды, определенные как ./.dircmdsнедоступные, непосредственно перед переключением и доступные сразу после переключения.
ShadSterling
-1

Вы можете использовать . script.shсинтаксис, пока скрипт, который вы хотите выполнить, находится в текущем каталоге.

Вы также можете добавить префикс к интерпретатору, например, sh или bash. пример:bash script.sh

UltimateByte
источник
8
. script.shсломается, если скрипт содержит exitнеожиданные эффекты, например, если он переопределил PATH «временно»; это также работает только для сценариев для вашей текущей оболочки
sourcejedi
@sourcejedi Что касается того, что exitвы можете поместить его в круглые скобки, то есть в подоболочку, но это правда, это все равно будет только для сценариев в той же оболочке.
phk
Вопрос говорит «исполняемый файл». Они не будут работать для двоичного исполняемого файла; только для скрипта. И твой второй абзац дублирует ответ Занны .
Скотт
Что ж, мой плохой, я в основном выполняю и разрабатываю bash, поэтому я предположил, что мы говорим о bash-скриптах :)
UltimateByte
Не только для скрипта, но только для скрипта Bash.
Оскар Ског