Bash for 循环“乱序”执行多个 echo 语句

Bash for 循环“乱序”执行多个 echo 语句

我有一个 bash 脚本:

for j in "$(ls -d */)"; do 
    echo "$j"
    echo "$j"
done

输出:

dir1/
dir2/
dir3/
dir1/
dir2/
dir3/

我想要它输出的是这样的:

dir1/
dir1/
dir2/
dir2/
dir3/
dir3/

我怎样才能让它以这种方式输出?

(这是一个玩具示例,我真的想要它做的是 cd 进入目录,做一些事情,然后 cd 返回,我意识到我可能可以通过一些字符串连接来完成相同的操作,但这种行为对我来说是如此令人困惑,我找不到任何其他问题所以我想我会问。)

答案1

你的循环确实如此迭代。在本次迭代中,变量j的值为

dir1/
dir2/
dir3/

然后你输出它两次。

该变量获取此值是因为您正在迭代单个字符串,即ls -d */.

要循环子目录,请使用

for dirpath in */; do
    printf '%s\n' "$dirpath"
    printf '%s\n' "$dirpath"
done

ls也就是说,根本不需要使用(ls是为了视力检查仅有的)。

cd在每次迭代中进入目录,请cd在子 shell 中执行 以及您需要在那里执行的任何操作。这样您就不必cd返回,因为当前工作目录是子 shell 的本地目录:

for dirpath in */; do
    ( cd -- "$dirpath" && some-command )
done

cd仅当您需要更改当前工作目录时才需要进入该目录some-command。大多数事情都可以从原始工作目录完成。

答案2

解析您正在做的输出ls并不是一个好方法。

但话虽如此,你的问题是引用:

rm -rf dir?
for j in 1 2 3; do mkdir dir$j; done
for j in $(ls -d */); do 
    echo "$j"
    echo "$j"
done
dir1//
dir1//
dir2//
dir2//
dir3//
dir3//

使用您的帖子中的引号,整个输出ls都包含在引号中,因此它被视为一个论点,导致for循环仅迭代一次,并将整个输出ls作为参数。您的代码尽职尽责地打印两次的整个输出ls

构建示例的ls更好方法是:

find . -type d -maxdepth 1 -mindepth 1 -exec printf '%s\n%s\n' "{}" "{}" \;

相关内容