«cd» inside «if» условие в Bash не меняет текущий каталог после «if» - PullRequest
0 голосов
/ 17 декабря 2018

Я пытаюсь выполнить условие "cd" inside "if" в скрипте Bash.Он остается в том же каталоге после «если».Так что я должен сделать "CD" снаружи "если", а затем использовать $?значение в если.Есть ли способ избежать использования этого дополнительного шага?Какой самый короткий способ сделать это?

Смотрите три варианта моего кода:

#!/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

1 Ответ

0 голосов
/ 17 декабря 2018

Скобки в bash создают вложенную оболочку - fork() -открытую копию оболочки с собственными переменными среды, собственным текущим каталогом и т. Д .;таким образом, в вашей первой попытке cd вступил в силу только до тех пор, пока закрывающая пара не закончила подоболочку. (POSIX не требует строго такого поведения подоболочки, но требует , чтобы среда, создаваемая в скобках, имела свой собственный рабочий каталог, поэтому эффекты cd будут применены ко всем стандартнымсовместимые оболочки, независимо от того, использует ли эта оболочка fork() здесь при любых обстоятельствах).

Используйте фигурные скобки, а не скобки, для группировки, когда вы не хотите создавать подоболочку.То есть:

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

Тем не менее, ваш второй подход прекрасно работает (хотя это неудобно для написания, а не обычная идиома).

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

... правильно испускает:

Starting in /tmp
Ending in /tmp/sim
...