cd 不将变量作为 bash 脚本中的参数

cd 不将变量作为 bash 脚本中的参数

我正在尝试制作一个 bash 脚本,它会给我一个命令,该命令将数字 n 作为参数,并将目录更改为通过在工作目录中运行 ls 列出的第 n 个目录。这是我所拥有的:

#! /bin/bash -
      
arg=$(ls --group-directories-first | awk -v first=$1 'NR == first' | tr -d '[[:space:]]')
cd $arg

这是行不通的。当我运行它时什么也没有发生。

第一行似乎确实以我想要的方式捕获目录名称。如果我将脚本更改为

#! /bin/bash -
      
arg=$(ls --group-directories-first | awk -v first=$1 'NR == first' | tr -d '[[:space:]]')
echo $arg

并在第一个目录是 bin 的目录中运行它,当我给它参数 1 时,脚本输出“bin”:

[user@manjaro ~]$ ls
bin/        
Desktop/    
Documents/  
Downloads/  
[user@manjaro ~]$ cdn 1
bin

那么为什么当我使用原始版本时 cd 不带“bin”并更改为 bin 呢?我应该如何改变它?

最后一点。当我尝试在脚本之外做类似的事情时,它工作正常:

[user@manjaro ~]$ foo=bin
[user@manjaro ~]$ cd $foo
[user@manjaro bin]$ pwd
/home/user/bin

再说一遍,为什么?

答案1

工作目录是正在运行的进程的一个属性,您的脚本在与 shell 不同的进程中运行。因此更改脚本中的目录不会影响您的交互式 shell。这是一件好事,否则类似的东西find可能会将你的 shell 留在任何随机目录中,尤其是。如果你在工作中打扰他们。

您可以将pwd脚本放在后面cd以查看它是否确实有效,如果是工作目录脚本变化。然后脚本退出。

将其改为一个 shell 函数:

cdn() {
    arg=$(ls --group-directories-first |
          awk -v first="$1" 'NR == first' | tr -d '[[:space:]]')
    cd -- "$arg"
}

(我不确定你为什么在tr那里。)

或者,在 Bash 中使用数组:

cdn() {
    dirs=( ./*/ )
    if [[ ${#dirs[@]} == 0 ]]; then
        echo "No directories!" >&2
        return 1
    fi 
    # minus one to go from one-based to zero-based indexing
    cd -- "${dirs[$1 - 1]}"
}

如果您的文件名带有换行符或空格,后者应该更安全。 (这不会检查是否存在与给定索引匹配的目录。如果不存在,它只会运行cd '',“更改”到当前目录。)

相关内容