递归搜索并在cmd中替换usind Perl(Windows)

Moh*_*ram 6 perl cmd

我正在使用此命令在命令提示符中搜索并替换另一个字符串:

 perl -pi -i.bak -e "s/Mohan/Sitaram/g" ab.txt
Run Code Online (Sandbox Code Playgroud)

这将替换MohanSitaram文件中的ab.txt当前目录.

不过,我想替换所有出现的MohanSitaram所有.txt文件中的所有子目录(递归).使用*.txt代替ab.txt不起作用.正则表达式工作,因为我已经下载了Windows的正则表达式包.它不适用于此命令说

E:\>perl -pi -e "s/Sitaram/Mohan/g" *.txt
Can't open *.txt: Invalid argument.
Run Code Online (Sandbox Code Playgroud)

有没有什么办法解决这一问题?也许是另一个命令?

jos*_*osh 7

find . -name "*.txt" | xargs perl -p -i -e "s/Sitaram/Mohan/g"

find 用于递归搜索所有*.txt文件.

xargs 用于从标准输入构建和执行命令行.


Pal*_*lec 6

Windows解决方案

在Windows上,可以使用该forfiles命令对多个文件执行命令.该/s选项告诉它以递归方式搜索目录.

forfiles /s /m *.txt /c "perl -pi -e s/Sitaram/Mohan/g @path"
Run Code Online (Sandbox Code Playgroud)

如果需要从当前工作目录以外的地方开始搜索,请提供/p path\to\start.

Unix解决方案

在Unix上,有一个比forfiles调用更通用的命令xargs,它将其标准输入的行作为参数传递给给定命令..txt使用该find命令以递归方式搜索目录以查找文件.

find . -name '*.txt' | xargs perl -pi -e 's/Sitaram/Mohan/g'
Run Code Online (Sandbox Code Playgroud)

平台无关的解决方案

您还可以在Perl中编写搜索文件和字符串替换的代码.该File::Find核心模块可以与帮助.(核心模块=与解释器一起分发.)

perl -MFile::Find -e 'find(sub{…}, ".")'
Run Code Online (Sandbox Code Playgroud)

但是Perl代码会更长,我不想花时间写它.使用File::Find上面链接的联机帮助页中的信息自行实现sub .它应该测试文件名是否以目录结尾,.txt并且不是目录,创建其备份并通过更改的备份版本重写原始文件.

Windows上的引用会有所不同 - 也许将脚本写入文件将是唯一合理的解决方案.

OP原始方法的问题

在Unix shell中,glob模式(例如*.txt)由shell扩展,而Windows cmd保持不变,并将它们直接传递给正在调用的程序.它的工作就是处理它们.Perl显然无法做到这一点.

第二个问题是,即使在Unix下,globbing也无法正常工作.*.txt.txt当前目录中的所有文件,不包括子目录及其子目录中的文件...