我正在尝试设计一个解决方案来重命名大量文件,以便每个文件的第 3 行中的文本是新文件名。这些文件都具有相同的结构。
这些是 HTML 文件,具体而言,每个文件的第 3 行如下所示。
<TITLE>DATA POPULATION 'CODE on group 1234 by THING'</TITLE>
我想获取单引号之间的所有内容,并使用该文本以该文本作为文件名来重命名该文件。
一次重命名这些会很有用。
答案1
for src in *.html; do
{ read -r x && read -r x && IFS="'" read -r x dst x; } < "$src" &&
mv -i -- "$src" "$dst.html"
done
(这-i
是为了交互的如果两个文件最终具有相同的目标名称,则使用户有机会避免丢失文件)。
答案2
$ awk -v FS="'" -v OFS="\t" 'FNR==3 && NF>2 {print FILENAME, $2; nextfile}' *.txt |parallel --colsep "\t" 'mv {1} {2}'
awk
迭代该位置中的所有文件。我们将 定义'
为字段分隔符。每当它到达第三行并且有超过 2 个字段(如果我们有两个字段就应该是)时,它会打印出文件名和由制表符分隔的'
第二个字段(前两个字段之间的部分)。'
然后它跳到下一个文件。
结果通过管道传输到parallel
.通过将和替换为结果列中给出的值来parallel
执行命令。mv
{1}
{2}
awk
一些注意事项:
nextfile
并非所有awk
版本都可用文件名中的空格从来都不是一个好主意。如果您
awk
像这样更改命令,则可以用下划线替换它们:awk -v FS="'" -v OFS="\t" 'FNR==3 && NF>2 { gsub(" ", "_", $2); print FILENAME, $2; nextfile}' *.txt
- 您应该将新文件名移动或复制到另一个文件夹。我不确定
awk
如果新文件在运行时出现在同一文件夹中会如何反应。
答案3
for j in ./*.txt
do
i=$( sed -n '3p' "$j" | cut -d "'" -f2)
mv "$j" "$i"
done
它将搜索当前目录中的所有文件,并将该文件移动到新目录。
答案4
我会在 Perl 中做这样的事情,而不是把一些缓慢而脆弱的子 shell 放在一起:
perl -e 'while(<>){
sub no_rename { print "rename @_\n" }
next unless $. == 3;
if(my ($f) = /DATA POPULATION +'\''(.*?)'\''/){
$f =~ s/[^\w]/_/g;
no_rename $ARGV, $f or warn "rename $ARGV, $f: $!\n";
}
close ARGV
}' files ...
您必须更改no_rename
为rename
使其真正执行,而不是显示它。
抱歉,丑了'\''
;如果你把它放在一个脚本文件而不是一行中,那应该很简单:
/DATA POPULATION +'(.*?)'/
如果您确实想创建带有空格的文件名,还可以在表达式\s
后面添加一个(对于文件名中可能出现的其他字符也类似 - 默认情况下,脚本将用下划线替换除字母和数字之外的所有内容)。\w
s///g