Executar como .test em vez de ./test

26

Supondo que eu esteja na mesma pasta que um arquivo executável, eu precisaria digitar isto para executá-lo:

./file

Prefiro não precisar digitar /, porque /é difícil para mim digitar.

Existe uma maneira mais fácil de executar um arquivo? Idealmente, apenas algumas sintaxes simples, como:

.file

ou qualquer outra coisa, mas mais fácil do que ter que inserir o /caractere lá.

Talvez haja alguma maneira de colocar algo no /bindiretório ou criar um alias para o intérprete, para que eu possa usar:

p file
IMSoP
fonte
9
Talvez troque / com outra chave usando o xmodmap? Então, pelo menos, é mais fácil digitar
Guy
26
Como uma observação lateral, /é amplamente utilizado no Unix, principalmente como um separador de diretório. Provavelmente, é melhor encontrar uma maneira mais fácil de digitá-la.
usar o seguinte comando
7
@RossPresser Esta questão faz muito pouco sentido desde então. e ./ no início do arquivo existem dois significados completamente diferentes por razões técnicas que qualquer iniciante deve saber. /não é difícil digitar para a grande maioria das pessoas e, se o OP tiver uma lesão que evite isso, eles deverão considerar layouts alternativos do teclado, pois não há como evitar /completamente enquanto estão no terminal.
JFA 07/02
1
@JFA A maioria dos layouts de teclado usados ​​na Europa continental e na América do Sul usa o /turno-7, que é relativamente difícil de digitar, mesmo sem ferimentos.
Nitro2k01
6
Editar história: " por que não posso interface de rede simplesmente ser instruído para fazer todas as consultas Internet através de um host remoto via ssh na porta 22. " ಠ_ಠ
Derek朕會功夫

Respostas:

35

Pode ser "arriscado", mas você poderia ter. no seu CAMINHO.

Como já foi dito em outros, isso pode ser perigoso, portanto, sempre garanta. está no final do CAMINHO e não no começo.

HaloJones
fonte
1
Realmente não vejo como isso é "arriscado": meu caminho tem sido assim desde muito antes do Linux, e nunca causou o menor problema.
jamesqf
21
@jamesqf É arriscado porque, se você acessar cdum diretório que possa ser gravado mundialmente e tentar usar um comando que não esteja no seu caminho, poderá executar um executável (possivelmente malicioso) com o mesmo nome que alguém escreveu nesse caminho. Isso é muito pior se você colocar .no início do seu caminho. Nesse caso, um executável malicioso chamado lsseria executado se você tentar chamar lsnesse diretório.
bytes
2
Evite isso pelos motivos especificados acima. O pcomando seria melhor.
Guido
11
@jamesqf Quando é o sistema "your", e somente você o utiliza, não é tão ruim assim. O problema vem (e atropelou muitos administradores Unix ao longo dos anos) no sistema multiusuário. No .início PATH, tudo que um usuário mal-intencionado precisa fazer é soltar um lscomando falso em seu diretório e convencer o administrador a "olhar para algo estranho" e eles têm acesso root.
TripeHound 7/02
1
Boa solução, embora não funcione se o arquivo for nomeado test, como no título da pergunta (já que testé um shell embutido e provavelmente também já existe em algum lugar no seu $PATH).
yellowantphil
71

.será preenchido automaticamente para./ (digitar .e pressionar Tab) pelo menos nos shells modernos do Bash; portanto, você não precisará usar uma PATHsolução complexa ou insegura (como modificação).

Se não for concluído automaticamente, pode ser necessário instalar o pacote "bash-complete".

l0b0
fonte
Você tem certeza? .possui vários candidatos à conclusão: .(dir atual), ..(dir pai), o .comando (que o bash fornece um alias fora do padrão source) e quaisquer arquivos de ponto presentes. Talvez o bash-completionpacote ignore isso; Eu acho isso atrozmente irritante (por exemplo, torna impossível completar os nomes de diretórios em uma makelinha de comando e geralmente é horrível com makefiles cheios de regras implícitas), por isso eu sempre limpo.
R ..
3
Eu tentei e, sim, é concluído automaticamente dessa maneira. Em quase todos os casos, é isso que um usuário comum gostaria: acho que nunca vi um arquivo de ponto que deveria ser executável, executar algo em um subdiretório é muito mais comum do que executar algo em um diretório pai, e no IMO um trabalho muito bom de encontrar makealvos.
L0b0 07/02
Com o bash 3.2, ele não é preenchido automaticamente. Isso poderia ser novo no bash 4?
Calimo 8/02
2
@Calimo Provavelmente novo nas versões recentes da conclusão do bash. Está longe de ser uma mudança fundamental.
L0b0
42

ou .. talvez dando ao intérprete um alias no arquivo bashrc e simplesmente

   p  file

É possível escrever essa função:

p() {
 ./"$@"
}

no seu ~/.bashrc. Então você poderá executar em p app argumentsvez de ./app arguments. Esta solução funciona para executáveis ​​de qualquer tipo, incluindo scripts e binários.

"$@"expande para uma lista de argumentos passados ​​adequadamente para a função (preservando todos os caracteres especiais da expansão glob ou variável) e, como apontado pelo @Scott, bashé inteligente o suficiente para acrescentar ./ao primeiro deles, preservando o restante.

aitap
fonte
Embora seja menos geral para executar o aplicativo com outro comando, gostaria strace -f p appde ver as chamadas do sistema feitas ou $(which time) p appde quanto tempo leva. pcomo um script executável funcionaria melhor nesses dois exemplos específicos que inventei. Nenhuma solução poderia funcionar ldd p app, embora ldd também seja diferente ao exigir um caminho completo, talvez por razões como essa.
sourcejedi
Sim, substituindo p app argscom ./app argsde uma forma que é invisível a qualquer um exigiria tubulação de entrada shell através de algum tipo de pré-processamento e iria causar todos os tipos de diversão quando a substituição ocorre em um lugar não intencional :)
aitap
1
Nesse caso, não deve haver aspas por aí $@? Caso contrário, ele passará apenas um grande argumento para o programa.
Kroltan 6/02
7
@Kroltan No. $@é uma matriz. Quando expandidos ", cada parâmetro se expande para uma palavra separada. $*se comporta do jeito que você está pensando.
8bittree
3
Acredito que você tenha feito isso desnecessariamente complexo, e isso p() { ./"$@"; }é tudo que você precisa.
7777 Scott
11

Você poderia colocar .a sua $PATHadicionando por exemplo, PATH=$PATH:.para o seu /etc/profile, desta forma você pode executar fileapenas por escrito file, a menos que seja em alguma outra pasta no seu caminho (por exemplo /usr/bin/). Observe que isso geralmente não é uma boa ideia.

Por que é ruim: diga que você está em uma situação em que não confia totalmente no conteúdo de um diretório - você o baixou de algum lugar desonesto e deseja investigá-lo antes de executá-lo, ou é um administrador de sistemas ajudando alguns procurando o diretório inicial, etc. Você deseja listar o diretório e tentar digitar ls, mas, oops, você digitou um erro de digitação e acabou digitando sl. O autor deste diretório malicioso antecipou isso e colocou um script de shell chamado "sl", que executa 'rm -rf --no-preserve-root /' (ou algo mais malicioso como instalar um rootkit).

(Obrigado @Muzer pela explicação)

phk
fonte
13
Embora eu concorde plenamente, provavelmente está explicando exatamente por que essa não é uma boa idéia.
58517 ymbirtt em:
16
Por que é ruim: diga que você está em uma situação em que não confia totalmente no conteúdo de um diretório - você o baixou de algum lugar desonesto e deseja investigá-lo antes de executá-lo, ou é um administrador de sistemas ajudando alguns procurando o diretório inicial, etc. Você deseja listar o diretório e tentar digitar ls, mas, oops, você digitou um erro de digitação e acabou digitando sl. O autor deste diretório malicioso antecipou isso e colocou um script de shell chamado "sl", que executa 'rm -rf --no-preserve-root /' (ou algo mais malicioso como instalar um rootkit).
Muzer # 6/17
2
Vale a pena explicar que, se o diretório atual estiver no início de $ PATH, o invasor poderá simplesmente substituir ls ou outros comandos comuns
Délisson Junio
@Muzer Huuuge chapéus de papel alumínio aqui.
Sombrero Chicken
4
@GillBates É o tipo de coisa que você precisa ter cuidado como administrador de sistemas que precisa lidar com usuários reais e potencialmente maliciosos ou como alguém que analisa arquivos suspeitos para sobreviver. Se nenhum deles se aplicar, concordo com você. Ainda acho que não é um bom hábito entrar, porque você nunca sabe quando suas circunstâncias vão mudar, você consegue um desses empregos e se amaldiçoará por ter se treinado para confiar em comportamentos inseguros; )
Muzer 07/02
10

Você pode ligar para o intérprete, por exemplo

bash test

Nesse caso, o script será executado mesmo que não tenha uma linha shebang (por exemplo #!/bin/bash) nem um bit executável. Você precisará conhecer o intérprete correto para executá-lo também. Você pode ler a linha shebang do arquivo primeiro para certificar-se de ligar para o intérprete correto, por exemplo, se a linha shebang indicar

#!/usr/bin/env python3

você ligaria

python3 test
Zanna
fonte
7
intérprete apenas interpretar o código, eles não vão executar arquivos binários
Mc Kernel
Essa resposta é um tanto lógica, porque talvez o intérprete possa receber um alias no arquivo bashrc.
5
@McKernel ponto bom, ele só funciona se houver um intérprete, não para executáveis compilados
Zanna
2
existe um intérprete para executáveis ​​compilados:/lib/ld.so
Dmitry Kudriavtsev
7

Até onde eu sei, não há como alcançá-lo, a menos que você inclua o arquivo no caminho env, portanto, você pode executá-lo apenas digitando: file

.filenão funcionará, pois esse é um nome de arquivo diferente. É um arquivo chamado .filee não ./file.

Sinto que a barra pode ser difícil de digitar para você, porque o layout não está em inglês, talvez? Nesse caso, isso também acontece comigo; portanto, frequentemente troco o layout do meu teclado para o inglês pressionando Alt + Shift no Windows (eu uso o Linux do ssh)

Mc Kernel
fonte
7

As pessoas sugeriram a adição .de PATH, o que é perigoso porque cria o risco de você acidentalmente executar um programa malicioso plantado em um diretório gravável em todo o mundo. Mas, se você tem programas executáveis em alguns diretórios que você possui e são gravável apenas por você, então é seguro (bastante seguro?) Para colocar aqueles diretor (es) em PATH, adicionando uma linha como

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

para o seu ~/.bashrcarquivo. Claro que isso significa que você pode executar um programa em um desses diretórios de qualquer lugar do sistema de arquivos. Por exemplo, você poderia cd /etcdigitar fooe ele seria executado ~/dev/myprog1/foo. Isso tem a pequena desvantagem de que você não pode ter programas com o mesmo nome em mais de um dos diretórios. Especificamente, se você tiver programas chamados foo em ambos ~/dev/myprog1e ~/dev/myprog2, não poderá executar o segundo, exceto especificando um caminho. Da mesma forma, se você tem um ~/dev/myprog1/cat- mas por que você gostaria?


Outra abordagem, se você tiver apenas alguns programas com isso, é definir aliases para eles:

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

Ou você pode chamar os apelidos .gizmoe, .gonzo se achar mais intuitivo.

Na verdade, isso tem, até certo ponto, o mesmo risco de segurança que você coloca .no seu PATH. Se um usuário mal-intencionado puder ler seu .bashrce ver seus aliases, ele poderá colocar o malware chamado gizmoe gonzoem diretórios aleatórios na esperança de que você o execute. É melhor usar esses nomes de caminho absolutos:

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

A propósito, você deve evitar nomear um executável test, porque esse é um comando interno do shell, e você pode executar um programa com esse nome apenas especificando um caminho ou algum outro truque.

G-Man Diz 'Reinstate Monica'
fonte
Como alternativa, você pode fazer uma receita (se você usar Makefiles) e fazer make gizmoou make gonzo.
ihato 7/02
Sinto muito, mas não sei ao certo como isso se relaciona à pergunta ou à minha resposta. Você está sugerindo que o OP crie um Makefileem cada diretório, para que as ações make gizmoterminem em execução gizmo ? (1) Essa parece uma maneira incômoda de fazer a mesma coisa que a pfunção, sugerida na pergunta, inicialmente implementada pela aitap e refinada por Scott. (2) Você pode passar argumentos dessa maneira? ISTM make gizmo arg1 arg2equivalente a make gizmo; make arg1; make arg2.
G-Man diz 'Reinstate Monica'
1
(1) Talvez minha suposição esteja errada, mas não está claro para mim que o OP deseja evitar o uso ./em todos os diretórios . Na minha opinião, ele está desenvolvendo algo e só precisa executar o programa produzido com ./filefrequência. Eu realmente não consigo pensar em qualquer outro cenário onde seria frequentemente precisam executar um arquivo local e se ele não estiver sendo executado com frequência ele não iria se preocupar fazer a pergunta (ele disse difícil não impossível ) (2) não é realmente mas você pode passar os argumentos na receita.
ihato 7/02
(1) Bem, acho que podemos concordar que a motivação do OP e o escopo de sua pergunta não são claros. (2) Obrigado pelo link.
G-Man diz 'Reinstate Monica'
3

Para expandir a resposta de Zanna sobre intérpretes (desculpe, sem repetições para comentar): um "intérprete" para executáveis ​​nativos (também conhecidos como arquivos binários ELF) é o loader dinâmico ( ld.so), mas normalmente não entende a sintaxe que você deseja:

$ /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>

(também, a menos que você faça um link simbólico ld.sopara o caminho, você ainda precisará escrever /s)

bacondropped
fonte
Isso é específico do Linux, certo? Você poderia explicar isso mais, por que isso funciona? Eu pensei que o kernel (Linux) faria a análise e decidir se e como executar um binário, binfmt_miscé para isso.
Php 06/02
2
@phk O arquivo é específico do Linux, mas o conceito de um vinculador / carregador dinâmico não é. Por exemplo, o FreeBSD tem o seu próprio /libexec/ld-elf.so.1. No Linux, não é tão simples quanto "decidir como executar um binário": binfmt_miscdetecta o formato do arquivo por números mágicos (ELF, script shebang, CIL). Depois disso, o binfmt_elfmanipulador é chamado. Ele analisa cabeçalhos e seções do ELF; .interpseção contém o caminho do carregador dinâmico; esse carregador é iniciado pelo kernel, realoca e pula para _start. No FreeBSD (não tenho certeza sobre os outros), não há binfmt, mas o princípio é +/- semelhante.
bacondropped 7/17
1
O @phk explica por que isso funciona - ld.sonão possui .interpe está vinculado estaticamente, o que significa que não é necessário outro vinculador / carregador dinâmico para resolver seus símbolos externos e fazer cálculos de relocação.
bacondropped 7/17
O ISTR Solaris também tem algo equivalente a isso.
G-Man diz 'Reinstate Monica'
3

Se pudermos começar a configurar as coisas

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

As distribuições mais modernas incluem ~ / .local / bin no $ PATH (adicione export PATH="$HOME/.local/bin:$PATH"ao seu ~/.profilese o seu não for o caso). Então você pode usar x filepara executar ./file.

Não tente definir um .comando. O comando . scriptjá é executado scriptno shell atual. Isso permite scriptdefinir variáveis ​​de ambiente para o shell atual.

sourcejedi
fonte
3
Acho que pode haver uma boa sugestão aqui, mas não há explicação sobre o que isso faz. Eu poderia resolver isso, mas um usuário inexperiente não teria chance.
IMSoP
Não há necessidade de mudar $ 1. Apenas exec "$@".
Reinierpost
$ (ln -s /bin/ls my-ls && exec my-ls) # bash: exec: my-ls: not found
sourcejedi
(1) Não há necessidade de shift $1; apenas exec ./"$@". (2) Como você está falando de um script de shell, é um pouco inútil / enganoso aconselhar as pessoas a não definirem um .comando, pois é impossível criar um arquivo chamado .. (É possível, e muito aconselhável, para definir uma função alias ou concha chamado ..)
Scott
1

Se pudermos criar scripts auxiliares, você poderá criar um auxiliar que adicione o pwd ao PATH e execute

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

Isso evita adicionar "." ao caminho e poluindo seu .profile com todos os caminhos em que você possa, em algum momento, querer executar algo.

Podemos levar essa abordagem um passo adiante, criando um auxiliar que lança um novo shell com um PATH modificado. Se usar um diretório como parâmetro (usando o pwd como padrão), ele funcionará como um pushdque edita o caminho. Você pode estar ciente de que quaisquer alterações em outras variáveis ​​de ambiente seriam perdidas ao sair do subshell, mas em um shell de longa execução, sua variável PATH não ficará confusa. Dependendo dos seus fluxos de trabalho, isso pode ser vantajoso.

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

Mas acho que se você quisesse rodar com ele, poderia hackear pushde popdassim eles podem fazer as mesmas modificações no caminho sem fazer um subshell que perderá outras alterações.

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

(Você não pode fazer o mesmo cdporque não possui um análogo popd.)

Você também pode criar um par de ajudantes dedicados para pressionar e abrir as entradas PATH. O que funciona melhor realmente depende dos seus padrões de uso.

ShadSterling
fonte
Na verdade, você pode fazer algo assim cd, mas está mais lá fora: Crie um arquivo como .dircmdse hackear cdpara tornar os comandos definidos em ./.dircmdsindisponíveis logo antes da troca e disponíveis logo após a troca.
precisa saber é o seguinte
-1

Você pode usar a . script.shsintaxe enquanto o script que você deseja executar estiver no diretório atual.

Você também pode prefixar o intérprete, como sh ou bash. exemplo:bash script.sh

UltimateByte
fonte
8
. script.shirá quebrar se o script contiver exit, tiver efeitos inesperados, por exemplo, se redefinir PATH "temporariamente"; ele também funciona apenas para scripts para o seu shell atual
sourcejedi
@sourcejedi Com relação a exitvocê pode colocá-lo entre parênteses, ou seja, um subshell, mas é verdade, ainda seria apenas para scripts no mesmo shell.
Php 06/06
A pergunta diz "um arquivo executável". Isso não funcionará para um executável binário; somente para um script. E seu segundo parágrafo duplica a resposta de Zanna .
7777 Scott
Bem, meu mau, eu principalmente executar e coisas dev bash, então eu assumi nós estávamos falando sobre scripts bash :)
UltimateByte
Não apenas para um script, mas apenas para um script Bash.
Oskar Skog