我有一个DE_CopyOldToNew.txt
文件,其中包含一大堆复制命令,用于将旧文件名复制到新文件名。
该文件包含如下行:
cp /migrationfiles/Company\ Name\ GmbH/2014.138_Old\ File\ Name.pdf /appl/data/docs/202403/DE_2014.138_NewFile_1.pdf
cp /migrationfiles/Company\ Name\ GmbH/2014.139_Old\ File\ Name.pdf /appl/data/docs/202403/DE_2014.139_NewFile_1.pdf
在我的 shell 脚本中,我迭代每一行并执行它。
echo "Start!"
while read -r line
do
command "$line"
done < /tmp/DE_CopyOldToNew.txt
执行脚本时,我会为读取的每一行获取以下内容......
: No such file or directory6: cp /migrationfiles/Company\ Name\ GmbH/2014.138_Old\ File\ Name.pdf /appl/data/docs/202403/DE_2014.138_NewFile_1.pdf
当从提示符下手动执行行时,它可以正常工作,不会出现错误......
答案1
问题是您正在将整行读入一shell 变量line
,然后使用引号(即 as "$line"
)。
虽然在使用 shell 变量时,特别是在处理(如您所做的)包含空格或其他“有问题”字符的文件名时,双引号通常是正确的,但在这种情况下,这意味着整条线cp
由命令组成及其论点在您的语句中被视为单个 shell 标记command
。
这意味着在循环中,您没有执行cp
带有参数/migrationfiles/Company\ Name\ GmbH/2014.138_Old\ File\ Name.pdf
和 的命令/appl/data/docs/202403/DE_2014.138_NewFile_1.pdf
,但 shell 尝试运行名为的可执行文件
cp /migrationfiles/Company\ Name\ GmbH/2014.138_Old\ File\ Name.pdf /appl/data/docs/202403/DE_2014.138_NewFile_1.pdf
其中用于分隔命令和参数的空格被解释为命令名称的一部分。这个可执行文件当然不存在。
您可以做的是将这些行读入三个变量,如下所示:
echo "Start!"
while read cmd arg1 arg2
do
command "$cmd" "$arg1" "$arg2"
done < /tmp/DE_CopyOldToNew.txt
假设结构始终采用示例中所示的形式。
笔记这个read
命令才不是包含该-r
选项,因为这会禁止将\
后面的空格解释为转义字符,但我们需要 shell 在这里执行此操作。
答案2
你说,
我有一个
DE_CopyOldToNew.txt
文件,其中包含一大堆复制命令,用于将旧文件名复制到新文件名。
...并且您说您要执行这些cp
命令。
您很幸运,因为您有一个 shell 脚本,即一个包含一组由 shell 按顺序执行的命令的文件。您需要做的就是让 shell 执行脚本中的命令:
sh DE_CopyOldToNew.txt
这将启动sh
一个基本 shell,并让它逐个命令执行文件的内容。
答案3
我不会让TXT文件做任何动作,而是将其视为数据源,因此使用脚本不仅可以执行需要执行的内容,还可以作为对数据的控制:
# Read each line of the file
while IFS= read -r line; do
# Get the files using awk with ' /' as separator.
# $line could have escaped spaces with '\ ' so we use parameter substitution →
# → to substitute them to unescaped spaces: "${line//\\ / }".
source_file=$(awk -F' /' '{ print "/"$2 }' <<<"${line//\\ / }") # source file
destination=$(awk -F' /' '{ print "/"$3 }' <<<"$line") # destination
# For example you can control that the source file exists
if [[ ! -f "$source_file" ]]; then
echo "The file $source_file does not exists!"
exit
fi
# The cp command is executed here
cp "$source_file" "$destination"
done </tmp/DE_CopyOldToNew.txt