如何从包含源值和目标值的大型文本文件中复制文件?

如何从包含源值和目标值的大型文本文件中复制文件?

我正在尝试编写一个脚本,该脚本将复制文本文件中列出的所有文件,大约 300 万行,其中包含两列,即源和目标,并使用新文件名:

path/to/source/directory/filename.pdf path/to/destination/directory/Newfilename.pdf
path/to/source/directory/filename2.pdf path/to/destination/directory/Newfilename2.pdf
path/to/source/directory/filename3.pdf path/to/destination/directory/Newfilename3.pdf
...

所有文件均为 PDF 格式,其中 Newfilename.pdf 是同一源 PDF 文件的新文件名。

另外,我想复制该文件并将信息添加到其目标文件名,即:

From:
Newfilename.pdf

To:
Newfilename_yyyyMMddHHmmss.pdf (e.g. Newfilename_20200225095823.pdf)

每个文件的实际复制执行日期和时间在哪里yyyyMMddHHmmss,这对于所有文件来说都是相同的格式,导致目标文件使用其补充名称进行复制:

path/to/destination/directory/Newfilename_20200225095823.pdf
path/to/destination/directory/Newfilename2_20200225095824.pdf
path/to/destination/directory/Newfilename3_20200225095830.pdf
...

我没有足够的知识来处理命令,我正在研究的想法如下:

#!/bin/bash
filename=$1

while read -r source destination; do
# reading each value
cp -p source destination
done < $filename

不过,我读过一些类似的出版物,为了表现,从文件或管道读取时,while 循环和读取速度非常慢,因为内置的 read shell 一次读取一个字符。参考这里

如何通过更好的解决方案来实现这一点?

我将非常感谢你的帮助。

答案1

抛开性能方面不谈,问题的第一部分可以使用 bash 的变量操作方法来解决:

timestamp="$(date +%Y%m%d%H%M%S)"

while read -r source destination; do
  newname="${destination/%.pdf/_$timestamp.pdf}"
  cp -p "$source" "$newname"
done < "$filename"

如果时间戳是“复制时刻”而不是调用脚本的时刻,则必须将调用date放在循环内:

while read -r source destination; do
  timestamp="$(date +%Y%m%d%H%M%S)"
  newname="${destination/%.pdf/_$timestamp.pdf}"
  cp -p "$source" "$newname"
done < "$filename"

更新:正如 @Jetchisel 所指出的,bash从 v4.2 开始,具有使用命令格式化日期的内置功能printf,这将使对外部命令的调用变得date不必要:

while read -r source destination; do
  printf -v timestamp '%(%Y%m%d%H%M%S)T'
  newname="${destination/%.pdf/_$timestamp.pdf}"
  cp -p "$source" "$newname"
done < "$filename"

相关内容