Bash For循环在下一次迭代之前更改回原始目录

时间:2018-09-10 16:43:53

标签: bash

我有一个for循环,该循环列出了所有可以正常工作的子目录,但是我想进入每个目录,运行命令,然后移至下一个目录,但它只是停留在它输入的第一个目录中。

脚本:

#!/bin/bash
for i in $(ls -l ../terraform/envs/ | grep ^d | tr -s ' ' | cut -d ' ' -f 9 );
  do
    echo $i | awk -v i="$i" !'/maint|template/'
    cd ../terraform/envs//$i
    echo $PWD
    break
    #terragrunt plan
done

2 个答案:

答案 0 :(得分:1)

使用pushd代替cd;那么您可以使用popd返回到原始目录。

不相关,但无需使用ls。改用glob。

cd terraform/envs
for i in */; do
    pushd "$i" > /dev/null
    echo "$PWD"
    popd > /dev/null
done

(当然,这里,循环前的cd命令意味着您可以只使用cd "$i"cd ..,但是pushd / popd可以很好地工作进行任意目录更改,而不仅仅是简单的一步一步的操作。)

(请注意,如果多次使用pushd,则需要向popd传递适当的参数,以确保返回正确的堆栈条目,或调用popd适当的次数。)

答案 1 :(得分:0)

首先,要回答您的问题,多亏了cd -命令,您可以返回上一个目录。它将打印出您回到的目录。如果您不想要该输出,请重定向到/dev/null,例如:

#!/bin/bash
for i in $(ls -l ../terraform/envs/ | grep ^d | tr -s ' ' | cut -d ' ' -f 9 );
  do
    echo $i | awk -v i="$i" !'/maint|template/'
    cd ../terraform/envs//$i
    echo $PWD
    cd - > /dev/null
    break
    #terragrunt plan
done

此外,就像@Cyrus提到的那样,解析ls输出通常是一个坏主意。有很多选择,我建议您从find中读取变量,例如:

while read i;
  do
  # do something
done < <(find ../terraform/envs/ -mindepth 1 -maxdepth 1 -type d)

最后但并非最不重要的一点是,您应该尽可能经常地将变量放在引号中,例如echocd中的内容,就像您对awk所做的一样。

总而言之,您应该得到这样的东西:

#!/bin/bash
while read i;
  do
    echo "$i" | awk -v i="$i" !'/maint|template/'
    cd "../terraform/envs//$i"
    echo $PWD
    cd - > /dev/null
    break
    #terragrunt plan
done < <(find ../terraform/envs/ -mindepth 1 -maxdepth 1 -type d)