我有一个 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' "{}" "{}" \;