循环变量的输出显示的值与预期不同

循环变量的输出显示的值与预期不同

想象一下我当前的工作目录中有两个文件夹:back/front/。我试图进入他们每个人的内心并做一些事情。从下面的简单脚本:

for dir in */ ; do
    echo "$(dir)"
done

我期待这样的输出:

back
front

然而,我得到的是:

back  front
back  front

我不明白。结果是,如果我尝试cd进入该文件夹:

for dir in */ ; do
    echo "$(dir)"
    cd $(dir)
    echo "$(pwd)"
    cd ..
done

我得到:

back  front
/path/to/back
back  front
/path/to/back

即我从不进入front/。有人可以帮助我理解我做错了什么吗?

答案1

在类似 POSIX 的 shell 中,$(cmd)语法是命令替换,扩展为减去尾随换行符$(cmd)的输出。cmd

你想要的是参数扩展:$dir${dir}(此处参数为dir 多变的)。

pwd( print working dictory) 是输出 1 特殊变量内容的命令,$PWD该变量本身包含当前工作目录的路径,因此只要不以换行符结尾,$(pwd)就会扩展为相同的内容。$PWD$PWD

所以你要:

for dir in */; do 
  (
    printf '%s\n' "$dir"
    cd -- "$dir" &&
      printf '%s\n' "$PWD"
  )
done

或者:

for dir in */; do 
  (
    printf '%s\n' "$dir"
    cd -- "$dir" &&
      pwd
  )
done

还请记住

  • echo不能用于输出任意数据,请printf改为使用
  • 您通常应该检查命令的退出状态。这里不检查 的输出cd意味着cd ..如果第一个失败,接下来的操作会将您带到错误的位置cd
  • cd最好在子 shell 中运行(使用(...))而不是使用,cd ..因为后者并不总是保证让您回到初始位置(如果涉及符号链接和/或某些路径组件已在间隔中重命名)
  • --当不能保证非选项不以开头-(或者+对于某些命令来说也可能是一个问题)时,必须使用 来将选项与非选项分开。
  • 在类似 POSIX 的 shell 中,参数扩展和命令替换(以及算术扩展)必须用引号引起来,否则它们会经历您通常不希望的隐式 split+glob(zsh 除外)。

另请注意,在 bash(以及除 zsh 之外的其他 POSIX shell)中,当 glob 与任何文件都不匹配时,它不会展开。

因此如果当前工作目录不包含任何可以确定为类型的非隐藏文件目录*/全局模式只会扩展到自身*/而不是空列表,您可能会看到一个错误,因为cd它无法进入该*/目录。

在 中zsh,您可以使用Nglob 限定符for dir in */(N); do...(或for dir in *(N-/); do...避免$dir以 结尾/)。

在 ksh93 中:for dir in ~(N)*/; do....

在 中bash,您可以nullglob暂时全局设置该选项:

shopt -s nullglob
for dir in */; do
  ...
done
shopt -u nullglob

为了完整起见,$(var)语法为Makefile命令使用的 s中的扩展make

在该awk语言中,$是取消引用字段的一元运算符,您只需用来var引用awk变量。因此,将与or$(var)相同并扩展到第th字段(如果为 0,则扩展到整个记录)。$var$ varvarvar

rc-like shell 中,与, , ,$(var)相同也可以工作,因为这是传递给 的一个元素的列表,因此您取消引用该变量,尽管您通常只使用.$var$ var$ 'var'$ ( 'var' )$var$var

在 TCL 中,$(var)将扩展为键名称为空的数组变量的值var

$ tclsh
% array set {} {foo 1 bar 2}
% puts $(foo)
1

是的,如果在这种情况下, PrintP没有多大意义。你可以猜到pwd命令(来自 70 年代中期的 Unix V5)是第一个,$PWD并且逻辑的POSIX 指定的当前工作目录的处理是后来出现的(在 80 年代初的 ksh 中,其中实际上是(是的,缺少和引号!)pwd的别名,并且在文档中被缩写为resent orking ictory)。有一个(当前orking目录)变量用于相同目的print - $PWD-r$PWDPWDtcsh$cwdcwd

相关内容