我正在尝试编写一个脚本,该脚本将复制文本文件中列出的所有文件,大约 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"