评估文件名,邪恶?

Mik*_*ren 4 bash shell-script

我有以下用于创建项目的脚本:

clear
version="0.0.2"
echo "Project creator"
echo "---------------"
# ask user to specify a directory (could start with spelled-out home directory)
directoryName=""
# Input must meet the following criteria: 
# 1.) No spaces at all in the directory path
# 2.) some characters must be entered
while [[ ${#directoryName} -eq 0 || $directoryName == *" "* ]]
        do
                echo -e "\nEnter the full directory of the project (no spaces):"
                read directoryName
        done
echo "You entered: $directoryName"
# uate directoryName so that the rest of the code can understand it
# create directory if it does not exist
eval mkdir "$directoryName"
# if successful
if [ $? -eq 0 ]
then
        # call executable in /home/miwarren/CPPFileCreator to create a main.cpp file to put in the folder
        $HOME/CPPFileCreator/a.out $directoryName
        # copy a run.sh file into the folder, too...
        eval cp $HOME/CPPFileCreator/run.sh $directoryName/run.sh
        # you might want to put a fileCreator.sh in the folder as well
        eval cp $HOME/fileCreator.sh $directoryName/fileCreator.sh
fi
Run Code Online (Sandbox Code Playgroud)

我确保去掉所有空格(假设每个不安全的字符串中至少有一个空格,因为注入式攻击)。我希望用户在存在变量时不必拼写路径部分(例如,$HOME对于主目录)。

我仍然可以eval在这里使用吗,如果不是,该怎么办?

Joh*_*024 6

“我希望用户在存在变量时不必拼写路径部分(例如,主目录的 $HOME)。”

这可以在没有eval

$ s='$HOME/.config'
$ s="${s//\$HOME/$HOME}"
$ echo "$s"
/home/john1024/.config
Run Code Online (Sandbox Code Playgroud)

这有一些限制。其一,如果双方家庭和家里要替代的话,以避免错误匹配的变量的名称,家庭必须取代之前HOME。

对所有导出的变量应用替换

使用 bash:

while IFS== read -r name val
do
   s="${s//\$$name/$val}"
done < <(printenv)
Run Code Online (Sandbox Code Playgroud)

例如:

$ export A=alpha; export B=beta
$ s='$HOME/$A/$B'
$ while IFS== read -r name val; do s="${s//\$$name/$val}"; done < <(printenv)
$ echo "$s"
/home/john1024/alpha/beta
Run Code Online (Sandbox Code Playgroud)

因为这种方法没有按长度对变量名进行排序,所以它有上面提到的变量重叠问题。

我们可以通过根据长度对变量名称进行排序来解决这个问题:

while IFS== read -r n name val
do
   s="${s//\$$name/$val}"
done < <(printenv | awk '/^[^ \t]/{key=$0; sub(/=.*/,"",key); printf "%s=%s\n",length(key),$0}' | sort -rnt=)
Run Code Online (Sandbox Code Playgroud)

如果用户输入一个存在的变量名称,但初始字符与某个较短的名称匹配,则较短的名称将被替换。如果这很重要,我们可以通过要求用户使用以下代码对此变量使用括号表示法来避免它:

while IFS== read -r n name val
do
   s="${s//\$\{$name\}/$val}"
done < <(printenv | awk '/^[^ \t]/{key=$0; sub(/=.*/,"",key); printf "%s=%s\n",length(key),$0}' | sort -rnt=)
Run Code Online (Sandbox Code Playgroud)

举个例子:

$ s='${HOME}/${A}/${B}'
$ while IFS== read -r n name val; do s="${s//\$\{$name\}/$val}"; done < <(printenv | awk '/^[^ \t]/{key=$0; sub(/=.*/,"",key); printf "%s=%s\n",length(key),$0}' | sort -rnt=)
$ echo "$s"
/home/john1024/alpha/beta
Run Code Online (Sandbox Code Playgroud)