简体   繁体   English

Bash中“ if”条件中的“ cd”在“ if”之后不会更改当前目录

[英]“cd” inside “if” condition in Bash does not change the current directory after “if”

I am trying to do "cd" inside "if" condition in a Bash script. 我试图在Bash脚本的“ if”条件内执行“ cd”。 It stays in the same directory after "if". 它在“ if”之后保留在同一目录中。 So I have to do "cd" outside "if" and then use $? 因此,我必须在“ if”之外执行“ cd”,然后使用$? value in if. 值如果。 Is there a way to avoid using this extra step? 有办法避免使用此额外步骤吗? What is the shortest possible way of doing it? 最快的方法是什么?

See three variants of my code: 查看我的代码的三个变体:

#!/bin/bash

set +e

# If I write the following:

if ! (rm -rf sim && mkdir sim && cd sim); then
    echo $0: Cannot prepare simulation directory
    exit 1
fi

# it does not change the current directory

echo $PWD

# Also, if I write the following:

if ! rm -rf sim || ! mkdir sim || ! cd sim; then
    echo $0: Cannot prepare simulation directory
    exit 1
fi

# it also does not change the current directory

echo $PWD

# In order to change the current directory, I need to write:

rm -rf sim && mkdir sim && cd sim

if [ $? -eq 1 ]; then
    echo $0: Cannot prepare simulation directory
    exit 1
fi

# Now it prints .../sim

echo $PWD
cd ..

# Is it possible to write it without an additional line with $?

exit

Parenthesis in bash create a subshell -- a fork() -ed off copy of the shell with its own environment variables, its own current directory, etc; bash中的括号创建了一个子外壳-一个fork() -从外壳副本中复制出它自己的环境变量,它自己的当前目录等。 thus, in your first attempt, the cd took effect only until the closing paren ended the subshell. 因此,在您的第一次尝试中, cd仅在结束括号结束子shell之前生效。 (POSIX doesn't strictly require this subshell behavior, but it does require that the environment created by parenthesis have its own working directory, so cd 's effects will be scoped on all standard-compliant shells, whether or not that shell actually uses a fork() here in all circumstances). (POSIX并不严格要求这种subshel​​l行为,但是它确实要求括号创建的环境具有其自己的工作目录,因此cd的作用将作用于所有符合标准的shell,无论该shell是否实际使用了在所有情况下都为fork() )。

Use curly brackets, not parenthesis, for grouping when you don't want to create a subshell. 当您不想创建子外壳时,请使用大括号而不是括号进行分组。 That is: 那是:

if ! { rm -rf sim && mkdir sim && cd sim; }; then
    echo "$0: Cannot prepare simulation directory"
    exit 1
fi

That said, your second approach works perfectly well (though it's unwieldy to write and not a conventional idiom). 也就是说,您的第二种方法非常有效 (尽管编写起来很笨拙,而不是传统的习惯用语)。

bash <<'EOF'
cd /tmp
echo "Starting in $PWD"
if ! rm -rf sim || ! mkdir sim || ! cd sim; then
    echo "$0: Cannot prepare simulation directory"
    exit 1
fi
echo "Ending in $PWD"
EOF

...properly emits: ...正确发出:

Starting in /tmp
Ending in /tmp/sim

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM