使用Shell脚本重命名文件,将文件名改为文件内的字符串。

4

我在论坛和stackoverflow上搜索了这个问题,但是没有找到答案。我正在使用Mac终端运行一个shell脚本来基于文件内容重命名一些pdf文件。

我有一个目录,里面装满了pdf文件,我正在使用开源的pdfbox将它们导出为文本文件。生成的文件与pdf文件同名,但以.txt结尾。我创建了这些文本文件,以便可以在文件中查找格式为Page xx Question xx的字符串,例如Page 43 Question 2。根据这个例子,我想将pdf文件重命名为pg43_q2.pdf

我认为我需要的正则表达式是: /Page\s+(\d+)Question\s+(\d+) 但我不知道如何读取两个捕获的数字并将它们保存到一个字符串中,以便我可以将其用作文件名。

到目前为止,我拥有的脚本是:

#!/bin/sh
PDF_FILE_PATH=$1
echo "Converting pdfs at $PDF_FILE_PATH"

find "$PDF_FILE_PATH" -name '*.pdf' -print0 | while IFS= read -r -d '' filename; do
   echo $filename
   java -jar pdfbox-app-1.6.0.jar ExtractText "$filename" "$filename.txt"
   NEWNAME=$(sed -n -e '/Page/s/Page\s+\(\d+\)\s+Question\s+\(\d+\).*$/pg\1_q\2/p' "$filename.txt")
   echo "Renaming pdf $filename to $NEWNAME"
   # I would do this next but the $NEWNAME is empty
   # mv "filename" "PDF_FILE_PATH$NEWNAME"
done

...但是sed命令没有将任何内容放入NEWNAME变量中。

我对sed并没有特殊的偏好,欢迎提出任何建议。

脚本的最新编辑使用了以下sed命令:

newname=$(sed -nE -e '/Page/s/^.*Page[[:blank:]]+([0-9]+)[[:blank:]]+Question[[:blank:]]+([0-9]+).*$/pg\1_q\2.pdf/p' "$filename.txt")

这种方法成功率约50%,但在重新命名文件时,新名称变量的其余时间为空。

已转换的文件中有效的第三行:

Unit 2 Review Page 257 Question 9  a)  12 (2)(2)(3)

转换后的文件中第三行无法正常工作:
Unit 2 Review Page 258 Question 16  a)  (a – 4)(a + 7) = a(a + 7) – 4(a + 7)                             = a2 + 7a – 4a – 28                              = a2 + 3a – 28   b)  (2x + 3)(5x + 2) = 2x(5x + 2) + 3(5x + 2)                                 = 10x2 + 4x + 15x + 6                                 = 10x2 + 19x + 6  c)  (–x + 5)(x + 5) = –x(x + 5) + 5(x + 5)                              = –x2 – 5x + 5x + 25                              = –x2 + 25  d)  (3y + 4)2 = (3y + 4)(3y + 4)                     = 3y(3y + 4) + 4(3y + 4)                     = 9y2 + 12y + 12y + 16                     = 9y2 + 24y + 16  e)  (a – 3b)(4a – b) = a(4a – b) – 3b(4a – b)                                = 4a2 – ab – 12ab + 3b2                                = 4a2 – 13ab + 3b2  f)  (v – 1)(2v2 – 4v – 9) = v(2v2 – 4v – 9) – 1(2v2 – 4v – 9)                                      = 2v3 – 4v2 – 9v – 2v2 + 4v + 9                                      = 2v3 – 6v2 – 5v + 9
1个回答

2

已删除无用的原始回答

echo 'Unit 2 Review Page 257 Question 9  a)  12 (2)(2)(3)'\
| sed -n '/Page/{s/.*Page[ ][ ]*\([0-9][0-9]*\)[ ][ ]*Question[ ][ ]*\([0-9][0-9]*\).*$/pg\1_q\2/;p;q;}'

输出

pg257_q9

echo 'Unit 2 Review Page 258 Question 16  a)  (a  4)(a + 7) = a(a + 7)  4(a + 7)'\
| sed -n '/Page/{s/.*Page[ ][ ]*\([0-9][0-9]*\)[ ][ ]*Question[ ][ ]*\([0-9][0-9]*\).*$/pg\1_q\2/;p;q;}'

输出

pg258_q16

否则,你是正确的!
(请注意,sed处理对两种情况都相同)。
我在末尾加了一个分号;p;q},并在开头加了一个左括号{,这样sed脚本就只会处理带有“Page”的行,然后退出。
我将posix字符类扩展到基本术语,即[[:digit:]]=[0-9],并用重复初始字符类后跟“零或多个”字符'*'来替换+,使[0-9][0-9]*。根据我的个人经验,在Sun 3上从OReilly的第二版Sed和Awk(带有组合装订!)学习sed时,所有posix的东西都是干扰和错误的另一个来源。显然,我在S.O上是少数派;-),但我愿意承认新的sed具有一些很棒的功能,在任何情况下......
我希望这可以帮助你。

在我的系统上,它在负号、十六进制D0处出现了故障,这应该与同一文本中的减号不同,但实际上并不是。例如,以下文本片段...Page 258 Question 16 a) (a – 4)(a + 7) = a(...会导致此输出:pg258_q16? 4)(a + 7) = a(... - GLaDOS
另外,我发现十六进制D0并不是标准ASCII字符。需要进行一些研究。我现在得走了,祝你好运。 - shellter
@shelter - 谢谢!这给了我一个解决方案的想法,但我得等到今晚回家后才能尝试。Apache pdfbox有一个参数-encoding <output encoding>,在这种情况下,我应该能够将pdf转换为仅ASCII字符(抱着希望,因为原始pdf中有很多Unicode字符),这应该解决sed在转换文本时遇到的问题。此外,在您发布的解决方案中有一个小错误,在第一个捕获组中:*\([0-9][[0-9]*\)多了一个左括号。 :) 所以很高兴你一直关注我的进展! - GLaDOS
抱歉之前拼错了你的用户名。问题:作为一个不熟悉sed的专家,我不应该假设;多余的左括号是打错了吗? - GLaDOS
另一个问题 - 你知道sed是否支持勉强量词吗?我刚在Java文档中读到了它,其中.*将读取整行并选择最大的匹配组,而勉强量词.*?将选择它能找到的第一个、最小的匹配组。请参见http://docs.oracle.com/javase/tutorial/essential/regex/quant.html - GLaDOS
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接