![如何批量重命名文本文件为每个文本文件中的第一个单词?](https://linux22.com/image/171787/%E5%A6%82%E4%BD%95%E6%89%B9%E9%87%8F%E9%87%8D%E5%91%BD%E5%90%8D%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E4%B8%BA%E6%AF%8F%E4%B8%AA%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8D%95%E8%AF%8D%EF%BC%9F.png)
我需要使用终端将几千个文本文件重命名为文本文件中的第一个单词加上文件扩展名 (.txt)。所有文件都位于一个目录中,当前以“xx0001.txt”到“xx9999.txt”模式命名。
每个文件中的第一个单词都是这种模式:“##221251”,所以也许我的问题来自需要注释掉英镑符号。
我试过了:
rename File.ReadAllText('*.txt').split(' ')[0]
这会引发错误:
zsh: no matches found: File.ReadAllText(*.txt).split( )[0]
在此先感谢您的帮助。我是一个真正的新手。
答案1
假设单词以 SPC、TAB 或 NUL 分隔,并且第一个单词位于第一行,请尝试:
for file (*.txt) {
read -r word rest < $file && mv -i -- $file $word.txt
}
要仅在 SPC 上拆分,请替换read
为IFS=' ' read
。
我不知道该rename File.ReadAllText('*.txt').split(' ')[0]
代码是用什么语言编写的,但这肯定不是zsh
语法(也不是我知道的任何其他 shell 的语法)。
zsh
我认为代码的用途的更直接的翻译是:
for file (*.txt) mv -i -- $file ${$(<$file)[1]}
尽管它会读取并拆分内存中的整个文件,并且不会进行太多错误检查。该拆分在 SPC、TAB、NUL 或 NL 上,并且不限于第一个在第一行。
为了使其更快,您可以zmodload zsh/files
预先运行,这会将命令替换mv
为内置版本(在调用时节省昂贵的 fork 和 exec)。
rename
它本身是一个示例程序的名称,该示例程序perl
至少从 80 年代就已发布。参数是perl
用于计算替换名称的代码。并非所有系统都附带该rename
命令,并且在某些系统上该rename
命令是完全不同的。如果你rename
是perl
这样的人,你可以这样做:
rename '
if (open FILE, "<", $_ and my $line = <FILE>) {
chomp $line;
my @words = split " ", $line;
$_ = "$words[0].txt" if @words;
}' ./*.txt
这里使用单引号,以便其中的内容被逐字传递为perl
语言perl
代码。
您可能还想更改*.txt
为*.txt(.)
或*.txt(-.)
仅考虑常规的文件(跳过目录、fifo、设备和其他非常规类型的文件)。
答案2
在vim
我会做以下(即使它很脏):
:$!ls *.txt
.txt
这为您提供了目录中所有文件的列表
:%norm A `sed 1q < | cut -f1 -d' '`
这会附加一个命令模板,该模板获取文件中的第一个单词(或者后面跟着一个空格的第一个单词,而不是[通常被认为是同一件事]),该模板将很快完成......
:%norm 0vf yf<p
从我们之前生成的列表中获取文件名并将其粘贴到<
:%norm Imv˽
在每行的开头添加移动命令和空格。
:w command.sh
将其保存为可以通过chmod +x command.sh
并运行的脚本./command.sh
警告:
没有搞卫生。也就是说,不会检查文件中的第一个单词是否是唯一的名称。这可能是由您的应用程序给出的,但在一般情况下并非如此。因此,将文件重命名为其内容的第一个单词可能会导致文件相互覆盖。因此,不建议这样做。