标题: [文本处理] 【已解决】批处理如何提取两个关键词之间的信息然后以此重命名文件名? [打印本页]
作者: ziranww 时间: 2019-1-29 16:39 标题: 【已解决】批处理如何提取两个关键词之间的信息然后以此重命名文件名?
本帖最后由 ziranww 于 2019-2-11 13:29 编辑
非常感谢论坛里热心的朋友们,特别是@flashercs帮我几次完善了脚本,非常感谢,问题解决了
最终完善版脚本在23楼http://www.bathome.net/redirect. ... 1962&pid=217302
有类似需求的朋友可以参考一下
--------------------------------------
RT,有大量文件需要重命名,改成TXT后发现了一些规律,从其中能提取到有用的信息用于重命名文件。于是在网上查,找到了一款神奇的软件Replace Pioneer,但是研究数个小时后还是没有搞定
看了半天官网上的规则和示例,折腾了几个小时未果。于是在网上查到了论坛,求高手帮忙
需要改名的文件改成TXT打开后是这样的:- 乱码
- abcd 乱码 name 乱码 efgh
- 乱码
复制代码
说明:
abcd:文件名标记信息开始
efgh:文件名标记信息结束
name:用于提取后重命名到文件名
谢谢了
作者: ziranww 时间: 2019-1-29 16:53
用notepad++打开是这样的,红圈部分是需要提取的文件名
作者: WHY 时间: 2019-1-29 19:07
应该不难。但无真实信息又没有样本,又是挤牙膏的节奏。
作者: ziranww 时间: 2019-1-30 08:52
回复 4# flashercs
谢谢兄弟,执行后没有成功,关了echo后看到有提示
ECHO 处于打开状态。
E:\test>set "dir=E:\test"
E:\test>powershell.exe -Command "(Select-String -Path 'E:\test\*.*' -Pattern '(?<=model_name\x00)[^\x00]+(?=\x00.*?disp_out1_info)' -Encoding default)|{Rename-Item -LiteralPath $_.Path -NewName $_.Matches[0].Value}"
所在位置 行:1 字符: 119
+ ... ng default)|{Rename-Item -LiteralPath $_.Path -NewName $_.Matches[0]. ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
只允许将表达式作为管道的第一个元素。
+ CategoryInfo : ParserError: ( [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ExpressionsMustBeFirstInPipeline
作者: zuodx 时间: 2019-1-30 13:11
perl python 正则表达式,写个脚本就是了
作者: ziranww 时间: 2019-1-30 14:04
回复 6# zuodx
这个更不会了
作者: flashercs 时间: 2019-1-30 14:19
回复 6# ziranww
a.bat- @echo off
- set "dir=E:\test"
- powershell.exe -Command "(Select-String -Path '%dir%\*.*' -Pattern '(?<=model_name\x00)[^\x00]+(?=\x00.*?disp_out1_info)' -Encoding default)|Foreach-object{Rename-Item -LiteralPath $_.Path -NewName $_.Matches[0].Value}"
复制代码
作者: ziranww 时间: 2019-1-30 14:38
回复 7# flashercs
兄弟,现在没有报错了,但是执行后没有改名
作者: flashercs 时间: 2019-1-30 15:00
好像没有规律可循,不好办;因为乱码部分是随机乱码。
作者: ziranww 时间: 2019-1-30 15:14
回复 9# flashercs
还是谢谢兄弟了
作者: 523066680 时间: 2019-1-30 16:35
本帖最后由 523066680 于 2019-1-30 16:55 编辑
回复 9# flashercs
正则应该有一种占位符用来表达常见字符或者明文以外的符号。
在Perl里面是 \p{组合属性},因为Perl基本很多人没装,就不安利楼主了。
丢个砖头- my $s = join('', map { chr } 0..127 );
- $s =~s/\p{IsCntrl}//g;
- print $s;
复制代码
过滤后的结果- !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
复制代码
建议楼主把eps文件压缩上传到某个网盘让大家下载看看,我用ai和coreldraw导出的eps文件并没有看到类似字段,没法测试。
如果按截图中处理的话大概会这么写
~/model_name\p{IsCntrl}+(.*)\p{IsCntrl}/;
取 $1
作者: lanfogz 时间: 2019-1-30 17:39
本帖最后由 lanfogz 于 2019-1-30 17:51 编辑
我的想法:先过滤乱码,再进行处理。
有个小工具(https://pan.baidu.com/s/1jIrZ5pB9wYyaFhx70GfScw),执行“smooth 文件名”
可以把结果粘贴上来,看看效果
理想的效果是:- @echo off &setlocal enabledelayedexpansion
- for /f %%i in ('smooth %1 ^|findstr model_name') do (
- set c=%%i
- rename %1 !c:10!
- goto:break
- )
- :break
复制代码
作者: WHY 时间: 2019-1-30 19:02
光看图片,猜测所谓的“乱码”指的是 [\x00-\x1F\x7F\x80-\xFF]
也就是 .net 正则中的 [\p{Cc}\p{IsLatin-1Supplement}]
作者: flashercs 时间: 2019-1-31 00:35
本帖最后由 flashercs 于 2019-1-31 09:58 编辑
由NULxE0NUL判断
这是utf8编码打开npp
而utf8编码下,\xE0\x00不存在编码位置,故替换为\xFFFD;
其他乱码同理:
所以文本分隔符应该是控制字符的[\x00-0x1f]和替换符\xFFFD- @echo off
- set "dir=E:\test"
- powershell.exe -Command "(Select-String -Path "%dir%\*.*" -Pattern '(?<=model_name[\x00-\x1F\uFFFD]+)[^\x00-\x1F\uFFFD]+(?=[\x00-\x1F\uFFFD]*disp_outl_info)' -Encoding utf8)|Foreach-object{Rename-Item -LiteralPath $_.Path -NewName ($_.Matches[0].Value+[System.IO.Path]::GetExtension($_.Path))}"
复制代码
作者: ziranww 时间: 2019-1-31 09:23
非常感谢论坛里热心的网友,已上传样本文件
是creo的prt文件
通过winhex打开看到情况是这样的,我现在通过replace pineer这个软件处理了一下文件,只能通过固定数量字符窜长度实现了一部分文件的提取后重命名,但是还是不完美,发现里面有许多文件命名长度不一样,最完美的是过滤掉乱码,提取两个字符中间的内容
作者: ziranww 时间: 2019-1-31 09:37
回复 11# 523066680
已上传,感谢版主
作者: flashercs 时间: 2019-1-31 10:00
14楼修改了
作者: ziranww 时间: 2019-1-31 10:05
回复 17# flashercs
万分感谢兄弟 成功
作者: ziranww 时间: 2019-1-31 10:08
回复 17# flashercs
再贪婪的问一下,因为有些文件是不同版本,文件名是一样的,能不能实现同样文件名文件,后面加上txt.1,txt.2这样的,谢谢了
作者: flashercs 时间: 2019-1-31 10:45
回复 19# ziranww - @echo off
- set "dir=E:\test"
- powershell -Command "(Select-String -Path '%dir%\*.*' -Pattern '(?<=model_name[\x00-\x1F\uFFFD]+)[^\x00-\x1F\uFFFD]+(?=[\x00-\x1F\uFFFD]*disp_outl_info)' -Encoding utf8)|ForEach-Object {$baseName = $_.Matches[0].Value + [System.IO.Path]::GetExtension($_.Path); $i = 0; $newName = $baseName; while ($true) {try {Rename-Item -LiteralPath $_.Path -NewName $newName -ErrorAction Stop; break; }catch {$newName = $baseName + '.' + (++$i); }}}"
复制代码
作者: ziranww 时间: 2019-1-31 10:49
回复 20# flashercs
谢谢大神,完美
作者: ziranww 时间: 2019-1-31 16:24
回复 20# flashercs
大神再问一下,我11点多执行的脚本,到现在还没有结束,大概1W多个文件,11G多点。看任务管理器,CPU还有占用的,30%不到点,硬盘读写基本上没有了,之前看是有一点的
是不是文件太多了?
作者: flashercs 时间: 2019-1-31 18:01
本帖最后由 flashercs 于 2019-1-31 19:42 编辑
加个进度看看吧,不知处理到哪里了。- @echo off
- REM UTF8编码,过滤控制字符和UTF8不能识别的字符后,选择字符串作为文件名并重命名文件。
- set "dir=%~dp0."
- powershell -Command "foreach ($item in (Get-ChildItem -LiteralPath \"%dir%\" -Filter *.* -File)) { if ([System.IO.File]::ReadAllText($item.FullName, [System.Text.Encoding]::UTF8) -match '(?<=model_name[\x00-\x1F\uFFFD]+)[^\x00-\x1F\uFFFD]+(?=[\x00-\x1F\uFFFD]*disp_outl_info)') { $baseName = $Matches[0] + $item.Extension; $i = 0; $newName = $baseName; while (Test-Path -LiteralPath (Join-Path -Path $item.DirectoryName -ChildPath $newName)) { $newName = $baseName + '.' + (++$i);} Write-Host 'Renaming file ' -NoNewline; Write-Host $item.FullName -NoNewline -ForegroundColor Green; Write-Host ' to ' -NoNewline; Write-Host $newName -ForegroundColor Green; Rename-Item -LiteralPath $item.FullName -NewName $newName; }}"
- pause
- exit /b
复制代码
作者: ziranww 时间: 2019-1-31 19:25
回复 23# flashercs
好像提示有点问题
Renaming file E:\test\1246.prt to ZKQ3003003.prt
Rename-Item : 无法重命名,因为“1246.prt”处不存在项。
所在位置 行:1 字符: 637
+ ... oundColor Green; Rename-Item -LiteralPath $item -NewName $newName; }}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: ( [Rename-Item],PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand
作者: flashercs 时间: 2019-1-31 19:43
回复 24# ziranww
已修改
作者: ziranww 时间: 2019-1-31 19:55
回复 25# flashercs
好的,不把文件后缀改成txt直接处理会不会有问题?
作者: flashercs 时间: 2019-1-31 19:59
回复 26# ziranww
测试目录测试一下!
默认筛选的是 *.*
作者: lanfogz 时间: 2019-2-1 09:51
- @echo off &setlocal enabledelayedexpansion
- for /r %%a in (*.txt) do (
- call:r %%a
- )
- goto:eof
- :r
- for /f %%i in ('smooth %1 ^|findstr model_name') do (
- set c=%%i
- set k=!c:~0,10!
- set v=!c:~10!
- if "!k!" equ "model_name" (
- if "!v!" neq "" (
- rename %1 !v!
- if errorlevel 0 (echo %1 to !v!) else (echo %1 to !v! ---- fail)
- goto:eof
- )
- )
- echo %1 ---- not found
- )
复制代码
https://pan.baidu.com/s/1o23mHiKZBrfNq_P73SVG9A
重在参与!
作者: ziranww 时间: 2019-2-13 11:06
回复 27# flashercs
你好,兄弟,用你的脚本把所有文件处理好了,现在又发现一个问题,重命名后的文件名比如是这样的:
a.prt
a.prt.1
a.prt.2
a.prt.3
.....
a.prt.250
我看了一下最大的文件到250,之前没注意,文件名应该是第一个开始就加.1,应该是这样的
a.prt.1
a.prt.2
a.prt.3
a.prt.4
.....
a.prt.251
我用原来找的几个批量命名的软件都无法实现扩展名,再求一个批量的脚本,谢谢了
作者: flashercs 时间: 2019-2-13 15:41
回复 29# ziranww
RenameFiles.bat- @echo off
- REM 重命名文件为其扩展名序号+1
- set "dir=E:\Dest\dest3"
- Powershell -Command "(Get-ChildItem -LiteralPath \"%dir%\" -Filter '*.*' -File|ForEach-Object {$ext = $_.Extension.Substring(1); if ($ext -match '^\d+$') {$id = [int]$ext}else {$id = 0}[PSCustomObject]@{'id' = $id; 'fileInfo' = $_}})|Sort-Object -Descending -Property 'id'|ForEach-Object {if ($_.id -ne 0) {$newName = $_.fileInfo.BaseName}else {$newName = $_.fileInfo.Name}$newName = $newName + '.' + ($_.id + 1); Write-Host ('Rename File \"' + $_.fileInfo.FullName + '\" to \"' + $newName + '\"'); Rename-Item -LiteralPath $_.fileInfo.FullName -NewName $newName}"
- pause
- exit /b
复制代码
作者: ziranww 时间: 2019-2-13 15:47
回复 30# flashercs
谢谢兄弟,分分种搞定了
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |