从bash中的另一个目录执行命令


119

说我正在这样做:

cd subdir
git init
cd ../

有没有一种方法可以使用一个或两个命令来执行此操作,而不必为了在该目录中运行命令而移入和移出目录?

(不寻找特定于git的解决方案;这只是一个示例。)

Answers:


202

这通常是最好的方法:

( cd dir ; git init )

要么

( cd dir && git init )

它很短而且易于输入。它确实启动了一个子外壳,因此您不能从那里修改您的环境,但是在这里似乎不是问题。


1
而且,如果确实需要设置一个或两个环境变量,只需在开头将其添加为另一个命令即可。
河马

1
@CraigMcQueen:不是真的。$?将包含在子外壳程序中运行的最后一个命令的退出代码。如果使用&&变体(通常应该这样做),那么您将获得第一个失败的命令的退出代码(如果一切正常,则返回0)。
马太福音

我认为括号是可选的
Francis.Beauchamp,

10
@ Francis.Beauchamp:如果省略括号,则将位于命令后的子目录中,而不是返回开始的位置。
Mat

在Windows上如何做到这一点?
卡尔·莫里森

22

我一直在寻找一种从路径执行git命令并在其他路径中对存储库进行更改的方法。所以我在这里结束了这个问题。

但是对于我的特定需求,既不能接受的答案也不能帮助其他任何人。

我需要使用sudo -u USER /usr/bin/git(另一个运行它的用户)运行git命令。正如你可能知道,须藤不允许我运行的cd命令,所以我不能成为存储库中的目录。

因此,我转到了git的手册页。在这些选项中,我看到了--git-dir=<path>

--git-dir =

设置存储库的路径。也可以通过设置GIT_DIR环境变量来控制。它可以是当前工作目录的绝对路径或相对路径。

因此,如果它可以帮助某人,您仍然可以从路径中使用git并“远离您”对存储库进行更改。只需使用:

git --git-dir=/path/to/repository GIT_COMMAND

或者,要以其他用户身份运行它,请执行以下操作:

echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir=/path/to/repository GIT_COMMAND

也来自git-init的手册页

如果设置了$ GIT_DIR环境变量,则它将指定用于存储库基础的路径,而不是./.git。

因此,如果要在通常的.git文件夹下初始化存储库,则需要将其与--git-dir选项一起指定。例如:

echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir=/path/to/repository/.git init

在上初始化存储库后/path/to/repo/.git,所有其他命令都应具有--work-tree=<path>git手册页中所述的选项:

--work-tree =

设置工作树的路径。它可以是绝对路径,也可以是相对于当前工作目录的路径。这也可以通过设置GIT_WORK_TREE环境变量和core.worktree配置变量来控制(有关详细讨论,请参见git-config(1)中的core.worktree)。

因此,以另一个用户身份运行git并初始化新存储库的正确命令是:

echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir=/path/to/repository/.git init
echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir='/path/to/repository/.git' --work-tree='/path/to/repository' add /path/to/repository/*
echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir='/path/to/repository/.git' --work-tree='/path/to/repository' commit -m 'MESSAGE'
echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir='/path/to/repository/.git' --work-tree='/path/to/repository' remote add origin user@domain.com:path
echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir='/path/to/repository/.git' --work-tree='/path/to/repository' push -u origin master

如果您是通过交互方式而不是通过脚本使用sudo,则可以简单地进行操作sudo -isudo su获取交互式root shell。
Bugster

我无法想象为什么( cd subdir && sudo -u USER /usr/bin/git init )不起作用。
斯科特

如果我没有访问权限怎么办subdir
dmmd

13

不完全是您要问的问题(您在subshel​​l上具有真正的答案),但请查看pushdpopd


我用cd &&尝试了maven,但没有用,但通过push和popd可以完美地完成工作。谢谢
Radu Toader

6

您有几种选择。您可以使用&&或将命令分组;。像这样:

cd subdir && git init && cd ..

要么

cd subdir; git init; cd ..

它们之间的区别在于,在第一个示例中,如果其中一个命令失败,它将不会执行其余命令。在第二个示例中,无论如何,所有命令都将运行。

另一个选择是定义一个函数并使用它,例如:

function cdinit() {
    cd $1
    git init
    cd ..
}

然后,您可以运行以下命令:

cdinit subdir

它将自动git init在该目录中移出。

如果您有一堆目录并希望git init使用一个命令来处理,则还可以使用函数来做一个更复杂的解决方案。

function cdinit() {
    for arg in $@
    do
        cd $arg
        git init
        cd ..
    done
}

然后可以使用以下命令运行它:

cdinit subdir1 subdir2 subdir3

它会做git initsubdir1subdir2subdir3


谢谢。我知道&&;,但是希望有一些更优雅的东西。听起来写脚本是我最好的选择。
Trevor Burnham

更正:这个答案很好,但是Mat的答案更适合我的特殊需求。
Trevor Burnham

您认为您的cdinit函数可以推广到任意命令吗?我尝试仅使用参数,但这没有用。
Chetan Bhasin

(1)换行符等效于;,因此三行功能等效于cd $1; git init; cd ..。(2)你应该引用您的变量:"$1""$@""$arg"。或者您可以缩写for arg in "$@"for arg
斯科特

5

如果是git(至少在版本2.7.0中),则可以利用-C使git像在给定目录中启动一样运行的选项。因此,您的解决方案可能如下所示:

> git -C subdir init
Initialized empty Git repository in /some/path/subdir/.git/

引用文档:

Run as if git was started in <path> instead of the current working directory. When multiple -C options are given, each subsequent non-absolute -C
<path> is interpreted relative to the preceding -C <path>.

This option affects options that expect path name like --git-dir and --work-tree in that their interpretations of the path names would be made
relative to the working directory caused by the -C option. 

2

您可以使用&&将命令分组,即

cd subdir && git init && cd ../

如果您不想依赖每个命令的退出代码,则可以使用; 相反,即:

cd subdir ; git init ; cd ../

1
或者;这样,它们就不依赖于前一个的返回码。
slhck 2011年

(1)  cd subdir && git init ; cd ..实际上可能最有意义。如果用户想在中运行git init命令subdir,那么他们可能不想在当前目录中运行该命令。即,如果(第一个)cd失败,他们不想运行它。(尽管cd失败的可能性很大,  因为我们已经在了subdir,但这是一个极端的情况。)…(续)
Scott

(续)…但是,如果用户希望将三个命令块视为一个单元,则cd即使git init命令失败,他们也可能希望  备份到起始目录。(或者,他们可能希望保留在子目录中并诊断命令失败。)(2)您不需要包括/after  ..
斯科特

2

如果该命令没有文件名或目录名参数,则必须跳到目标目录。

但是您可以编写一个以目标目录和命令为参数的bash脚本。为此,您可以看一下push和popd:http : //ss64.com/bash/pushd.html

我会为您编写一个小脚本,但是这里没有Linux框:)


刚刚看到Mark Szymanski的回答。您可以只为命令实现第二个参数(并重命名命令),然后您便拥有了所需的内容。
wullxz 2011年

1

程序使用不同的方式处理参数,因此有些程序将具有-folder = name选项。除了该例外,即使在MS DOS上,该标准也很简单

$ 程序子目录

有时候你需要

$ program subdir /

该程序将打开该文件夹,并以与处理文件相同的方式使用该文件夹,完成后,将控制权返回到指向原始标准目录的Shell。以这种方式处理的程序确实存在错误输出(如核心转储)进入外壳程序当前目录(而不是subdir)中的文件的问题。

除非程序具有可用于指定其他位置的命令开关,否则没有解决方法。一些程序员在“ 从调用目录程序”和“ 告诉目录程序在其中工作 ” 之间获得了艺术许可。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.