Existe um utilitário POSIX (ou pelo menos um popular) para definir o diretório de trabalho atual ao chamar um programa?

20

Temos o env (1) para modificar o ambiente do comando que queremos executar (por exemplo env MANPAGER=more man dtrace). Existe algo semelhante, exceto para modificar o diretório em que o comando será iniciado?

Idealmente, eu gostaria que fosse assim:

theMagicCommand /new/cwd myProgram

Dessa forma, ele pode ser "encadeado" com outros comandos do tipo env (1), por exemplo,

daemon -p /tmp/pid env VAR=value theMagicCommand /new/cwd myProgram

Até agora, posso pensar na seguinte solução, que infelizmente não possui a mesma interface que env (1):

cd /new/cwd && myProgram

Além disso, eu posso apenas criar um script de shell simples como este:

#! /bin/sh -
cd "${1:?Missing the new working directory}" || exit 1
shift
exec "${@:?Missing the command to run}"

mas estou procurando por algo que já existe (pelo menos no macOS e no FreeBSD).

myProgramnão é necessariamente um aplicativo de desktop (nesse caso, eu poderia apenas usar a chave Path em um arquivo .desktop ).

Mateusz Piotrowski
fonte
6
Por que cd /new/cwd && env VAR=value myProgramnão atende aos seus critérios?
jpaugh
Isso já está em questão, onde M. Piotrowski explicou que essa não é a mesma interface que env. Olhe para env. Compare-a rtprio, idprio, numactl, jexec, chrt, e de fato os comandos nos conjuntos de ferramentas mencionado nas respostas. Existe um padrão e é o carregamento em cadeia.
JdeBP
3
O que você quer dizer com "interface"? E por que não usar (cd the/cwd; cmd)?
Konrad Rudolph
2
@KonradRudolph Por exemplo, você não pode passar facilmente (cd the/cwd; cmd)para env (1) sem agrupá-lo com sh (1).
Mateusz Piotrowski

Respostas:

19

AFAIK, não existe um utilitário dedicado no baú de ferramentas POSIX. Mas é comum chamar shpara configurar um ambiente (cwd, limites, stdout / in / err, umask ...) antes de executar um comando como você faz em seu shscript.

Mas você não precisa escrever esse script em um arquivo, basta inseri-lo:

sh -c 'CDPATH= cd -P -- "$1" && shift && exec "$@"' sh /some/dir cmd args

(supondo que o diretório não seja -). Adicionando CDPATH=(no caso de haver um no ambiente) e -Ppara que ele se comporte mais como um straight chdir().

Como alternativa, você pode usar perlquem chdir()faz uma linha reta chdir()fora da caixa.

perl -e 'chdir(shift@ARGV) or die "chdir: $!"; exec @ARGV or die "exec: $!"
         ' /some/dir cmd args
Stéphane Chazelas
fonte
Oh sim. Isso indica uma variação muito útil do script que incluí na minha pergunta. Eu estava com medo de que o utilitário que eu estou procurando não exista, pois sua funcionalidade já está disponível com um oneliner sh (1) relativamente curto.
Mateusz Piotrowski
8
Se você já está executando sh, também pode fazê-lo (cd /wherever && exec /my/command). O ()abre implicitamente um subnível para executar os comandos embrulhadas, e, claro, execse livrar do processo de shell extra como rapidamente /my/commandcomeça a funcionar.
jpaugh
2
Isso foi sugerido em uma resposta excluída agora. O questionador explicou que isso não era uma resposta ao que xe perguntou.
JdeBP
15

Os conjuntos de ferramentas usados ​​no mundo daemontools e em outros lugares têm isso e muito mais; teve por muitos anos; e estão amplamente disponíveis.

Todas essas são ferramentas de carregamento de corrente, projetadas para serem usadas exatamente nesse tipo de corrente. Há uma grande variedade de ferramentas de carregamento em cadeia nesses kits de ferramentas para outros fins.

Leitura adicional

JdeBP
fonte
11

Existe um programa tão popular. Ele é chamado ... hold em sua cadeira ... drumroll ... env. A versão GNU, desde a versão 8.28, não POSIX, tem a -Copção que permite definir o diretório exatamente como você deseja:

    NOME
           env - executa um programa em um ambiente modificado

    SINOPSE
           env [OPÇÃO] ... [-] [NOME = VALOR] ... [COMANDO [ARG] ...]

    DESCRIÇÃO
           Defina cada NAME como VALUE no ambiente e execute COMMAND.

           Argumentos obrigatórios para opções longas também são obrigatórios para opções curtas.

           -i , --ignore-environment
                  comece com um ambiente vazio

           -0 , --null
                  finalize cada linha de saída com NUL, não nova linha

           -u , - pôr do sol = NAME
                  remover variável do ambiente

           -C , --chdir = DIR
                   altera o diretório de trabalho para DIR

           --help exibe esta ajuda e sai

           --versão
                  informações da versão de saída e saída

           Um mero - implica -i . Se não houver COMANDO, imprima o ambiente resultante.

n. 'pronomes' m.
fonte
Legal, embora não esteja disponível imediatamente no macOS e no FreeBSD.
Mateusz Piotrowski
1

Certos programas têm uma opção para isso, como o Git:

-C <path>

Execute como se tivesse gitsido iniciado no <path>lugar do diretório de trabalho atual.

e fazer:

-C dir, --directory=dir

Mude para o diretório dirantes de ler os makefiles ou fazer qualquer outra coisa.

e alcatrão:

-C, --directory=DIR

Mude para DIRantes de executar qualquer operação. Esta opção é sensível à ordem, ou seja, afeta todas as opções a seguir.

Steven Penny
fonte
Sim. Embora minha pergunta seja: o que se myProgramnão oferece essa opção ... Obrigado por sua contribuição, mas receio que ela não responda à minha pergunta.
Mateusz Piotrowski