【问题标题】:how to pass a variable through read in bash如何通过在bash中读取来传递变量
【发布时间】:2014-11-26 18:53:45
【问题描述】:

我正在尝试制作一个脚本来询问目录路径,然后创建该目录。我希望能够将变量传递给 read 内置路径名,这样我就不必输入完整路径:

function make_dir {
echo "What is the path of the directory to be created?"
read directory
mkdir "$directory"
}

所以我会输入:

make_dir
What is the path of the directory to be created?
$HOME/temp_dir
mkdir: cannot create directory `$HOME/temp_dir': No such file or directory

所以我想将 $HOME 扩展为 /home/user/ 和创建目录 /home/user/temp_dir 的脚本,但我似乎无法让扩展工作。

如果我将下面的make_dir函数修改为show_dir

function show_dir {
echo "What is the path of the directory to be created?"
read directory
echo "The directory is $directory"
}

然后我输入$HOME/temp_dir 并得到以下信息:

make_dir
What is the path of the directory to be created?
$HOME/temp_dir
The directory is $HOME/temp_dir

没有扩展。关于如何让它发挥作用的任何想法?

【问题讨论】:

  • 唯一的答案是eval,这不是一个好的解决方案。使用read -e 选项卡完成可能会为您展开它,并且任何展开变量的读取行绑定(如meta-ctrl-eesc ctrl-e)都会在您按Enter 之前展开它。
  • 感谢您的回复,在mkdir "$directoy" 前面添加eval 似乎可行,您能帮我理解为什么这不是一个好的解决方案吗?
  • @BrianAlbertMonroe 问题是如果$directory 扩展为some string; rm -rf /* 之类的东西。 eval 然后得到字符串echo some string; rm -rf /* 来执行。

标签: bash shell variables mkdir


【解决方案1】:

这有点麻烦,但一种选择是使用-e 标志告诉read 使用Readline 获取输入,然后在键入后使用Readline 扩展行,但在按Enter 之前。

$ read -e directory
$HOME/dir

现在键入 Meta-Control-e,Readline 将扩展输入,就像它在执行之前被处理一样外壳命令。 (请注意,Meta 键可能是 Alt 或 Esc,具体取决于您的终端设置。)

【讨论】:

  • 我想比遇到eval 灾难要好,但正如您所说,它很麻烦,并且不会将~ 扩展到/home/user
  • 它应该扩展~
  • 那里有一个程序,它接受一个字符串并输出通过替换输入中任何 environment 变量的值而产生的字符串,但对于我的一生,我不记得叫什么了。
  • 奇怪,我又试了一次,它成功了。一定是按错键了。该程序将是完美的,如果您记得请张贴。在那之前,我想我只会为这个特定的功能输入完整的路径。
【解决方案2】:

您实际上是通过尝试使用read 获取目录使事情变得更加困难。除非您绝对需要使用read,否则最好将目录传递给您的函数as an argument。例如:

function make_dir {
    [ -n "$1" ] || {
        printf "\n usage: make_dir <path_to_create>\n\n"
        return 1
    }
    mkdir -p "$1" || {
        printf "\n error: unable to create '$1', check permissions\n\n"
    }
}

示例:

$ function make_dir {
>     [ -n "$1" ] || {
>         printf "\n usage: make_dir <path_to_create>\n\n"
>         return 1
>     }
>     mkdir -p "$1" || {
>         printf "\n error: unable to create '$1', check permissions\n\n"
>     }
> }

$ make_dir $HOME/temp_dir

$ ls -al temp_dir
total 8
drwxr-xr-x  2 david david 4096 Nov 26 15:34 .
drwxr-xr-x 76 david david 4096 Nov 26 15:34 ..

$ make_dir

usage: make_dir <path_to_create>

当您将目录传递给函数as an argument 而不是使用read 时,您也可以轻松地将函数调整为take/create multiple directories

function make_dir {
    [ -n "$1" ] || {
        printf "\n usage: make_dir <path_to_create> [path2, ..]\n\n"
        return 1
    }
    for i in "$@" ; do
        mkdir -p "$i" || {
            printf "\n error: unable to create '$i', check permissions\n\n"
        }
    done
}

示例:

$ make_dir temp_dir_{1..3}
$ ls -1d temp_*
temp_dir_1
temp_dir_2
temp_dir_3

【讨论】:

  • 我喜欢这个解决方案。
  • 对函数使用参数对我的情况没有帮助。该函数在一个较大的脚本中调用,该脚本要求用户创建一个路径,因此需要read
  • 很公平,我只是根据您的示例工作。但在您的更大范围内,read 很好。
【解决方案3】:

更改以下行:

mkdir "$directory"

eval mkdir -p "$directory"

【讨论】:

  • 非常危险;这允许恶意用户制作包含任意命令行的“目录名”,然后执行。使用[[ -d $directory ]] &amp;&amp; eval mkdir -p "$directory" 进行验证会好一些,但我仍然建议不要在此处使用eval
猜你喜欢
  • 1970-01-01
  • 2019-06-05
  • 1970-01-01
  • 2019-05-25
  • 2012-10-01
  • 2014-02-06
  • 1970-01-01
  • 2013-02-07
  • 2018-09-20
相关资源
最近更新 更多