将文件复制到不同目录的简单脚本的输入存在问题

将文件复制到不同目录的简单脚本的输入存在问题

作为一个正在学习 bash 的人,我一直在编写简单的脚本来测试各种命令。在下面的简单脚本中,我正在尝试使用 read 命令。

#!/bin/bash
read -p "Enter a path to a file: " file_to_copy
cp $file_to_copy /tmp

如果用户在提示时输入测试文件的完整路径,例如 /home/$USER/test,则脚本将按预期执行并在 /tmp 目录中复制“test”。但是,如果用户输入简写 ~/test,终端将返回错误cp:无法统计‘~/test’:没有此文件或目录。为什么输入cp命令时无法找到文件路径的等效表示?

如果我独立在终端输入:

cp ~/test /tmp

测试文件顺利复制,所以可能是我搞砸了变量分配的细微差别,但我无法弄清楚。

谢谢。

答案1

在您的脚本中尝试以下命令:

#!/bin/bash
read -p "Enter a path to a file: " file_to_copy
file_to_copy=$(bash -c "echo $file_to_copy")
file_to_copy=${file_to_copy/~\//$HOME\/}
cp "${file_to_copy}" /tmp

解释:

  • env如果存在变量值,第三行将扩展它。

  • ~上述代码的第四行将尝试在您的变量中搜索file_to_copy,如果找到,它将被$HOME路径替换。

  • \/\的反斜杠转义序列字符/,因为我们想用~/替换$HOME/

答案2

实际情况是,你实际上是要求 shell 从脚本当前所在的目录中查找~/test。换句话说,如果你从 运行,它将在名为 的子目录中/home/$USER寻找文件,而不是扩展名。test~/home/$USER/test

您可以使用bash内置的 eval,它将接受任何参数并将它们组合成一个命令,然后让 shell 运行它。现在,shell 将扩展~

xieerqi:
$ ./copyScript.sh                                                                                                       
Enter a path to a file: ~/test
Entered /home/xieerqi/test

xieerqi:
$ ls -l /tmp/test
-rw-rw-r-- 1 xieerqi xieerqi 0 Dec 21 01:14 /tmp/test

xieerqi:
$ cat copyScript.sh
#!/bin/bash

read -p "Enter a path to a file: " file_to_copy
file_to_copy=$(eval echo $file_to_copy)
echo "Entered $file_to_copy"
cp "$file_to_copy" /tmp

我建议您也使用引号括住命令替换$( . . .),以确保包含空格和特殊字符的文件能够被正确捕获到file_to_copy变量中

添加

正如评论中所说,eval内置可能会很危险。

readlink就我个人而言,我在脚本中经常使用命令,并避免使用~。既然在这个脚本中你无论如何都会要求用户输入,为什么不使用命令行参数呢?像这样:

xieerqi:
$ ./copyScript.sh testFile.txt                                
/home/xieerqi/testFile.txt

xieerqi:
$ cat copyScript.sh                                           
#!/bin/bash

FILE="$(readlink -f "$@" )"

echo $FILE
# uncomment for copying
# cp $FILE /tmp

目录名和基名

GNU coreutils 提供了两个命令,basenamedirnamebasename显示路径中的最后一个元素,并dirname显示最后一个元素之前的所有内容。可以使用bash的内部参数扩展来执行相同操作,但既然我们有这些工具 - 为什么不使用它们:

xieerqi:
$ ./copyScript.sh                                             
Enter path to file: ~/testFile.txt
File entered is  /home/xieerqi/testFile.txt

xieerqi:
$ ./copyScript.sh                                             
Enter path to file: ~/sumFile.txt
File entered is  /home/xieerqi/sumFile.txt
ERROR, file doesn't exist

xieerqi:
$ cat copyScript.sh                                           
#!/bin/bash

read -p "Enter path to file: " FILEPATH

DIRPATH="$(dirname "$FILEPATH")"
FILENAME="$(basename "$FILEPATH" )"

if [ "$DIRPATH" == "~"   ];then
  DIRPATH="$HOME"
fi

FILEPATH="$DIRPATH"/"$FILENAME"
echo "File entered is " "$FILEPATH"

[ -e "$FILEPATH"  ] || { echo "ERROR, file doesn't exist"; exit 1;}

相关内容