2017-02-22 79 views
0
@Echo off&SetLocal EnableExtensions EnableDelayedExpansion 
cd "C:\Documents and Settings\John\Desktop\New\Interest\f2" 
Pushd "C:\Documents and Settings\John\Desktop\New\Interest\f2" 
Set Line#=26 
Set /A LOfs=24 -1, Len=34 - LOfs 
For %%A in (*.txt) do For /F "tokens=1* delims=:" %%B in (
    'Findstr /N ".*" "%%A" ^|Findstr "^%Line#%:"' 
) do if %errorlevel% == 0 Set "Line=%%C"&Ren "%%~fA" "!Line:~%LOfs%,%Len%! - %%A!"" 
Popd 

在上面我试图改变文件的文件名在文件中的某个位置。批处理文件重命名目录中的文本文件从文本文件中的文本文件在特定的行除外如果行空白

如果第26行为空,则不做任何操作,也不要更改文件名。

我在某个地方出了问题,正在圈圈。

任何人都可以帮忙吗?

谢谢。

+0

为什么在'do'条件结尾处有两个引号?这会将ren命令设置为'line'变量值。 – npocmaka

+1

你期待'ErrorLevel%== 0'接收到什么'ErrorLevel'? 'findstr'之一?这是行不通的,因为'findstr'是在新的'cmd'实例中由'for/F'执行的。另外,您需要[延迟扩展](http://ss64.com/nt/delayedexpansion.html)用于'!ErrorLevel!';或者,你可以使用'如果不是ErrorLevel 1'。无论如何,因为无论如何你都在过滤第26行,毕竟你可能不需要任何'if' /'ErrorLevel'查询。 'ren'命令行后面有一个''''但是,你应该提供一个例子,并且你应该描述实际发生的事情... – aschipfl

+0

我认为**如果%ErrorLevel%== 0 **会如果发现** Findstr/N“*”“%% A”^ | Findstr“^%Line#%:**不是空行。 – jaburmester

回答

0

你没有说明脚本如何失败,但我可以看到一些潜在的问题。我也看到可能的简化。

  • 你肯定不会同时需要CDPUSHD
  • 我摆脱了数字变量,包括在实际的数字代码文字。如果需要,您可以恢复到变量。
  • 您不需要外部的FOR循环。 FINDSTR可以在文件名中使用通配符时搜索多个文件,然后它将包含文件名,然后在输出中输入:。因此,如果添加/N选项,输出格式将为filename:line#:text。然后,您可以调整第二个FINDSTR以仅返回正确的行号。
  • 仅仅忽略空行是不够的。只有在第23个字符后至少有一个有效的文件名字符时,您的重命名才起作用。文件名不能包括:,*,?, /,\,<,>|。 (我可能错过了一些)。我调整了FOR /F分界点和FINDSTR搜索来补偿。
  • 对于像%%A这样的变量扩展,如果它们包含!并且启用延迟扩展,将会损坏值。 !是文件名中的有效字符。所以延迟扩展必须在循环内开启和关闭。

我相信下面会做你想做的。下面的代码只会回显重命名命令。在ren提供正确结果后,请删除ECHO

@echo off 
setlocal disableDelayedExpansion 
pushd "C:\Documents and Settings\John\Desktop\New\Interest\f2" 
for /f "tokens=1,3 delims=:*?\/<>|" %%A in (
    'findstr /n "^" "*.txt" ^| findstr "^[^:]*:26:.......................[^:*?\\/<>|]"' 
) do (
    set "old=%%A" 
    set "line=%%B" 
    setlocal enableDelayedExpansion 
    ECHO ren "!old!" "!line:~23,11! - !old!" 
    endlocal 
) 
popd 
+0

变量的用法源于我的回答OP [第一个非常相似的问题](http://stackoverflow.com/questions/42278373/)。他没有在那里显示很多自己的努力,也没有兑现完整的答案。当我拒绝将我的答案延伸到一个新问题时,上面的代码是从我的答案中获得的(还有一些错误增加了)。 – LotPings

+0

@LotPings - 有趣的历史。谢谢。 – dbenham

0

一种略有不同的方法来戴夫斯:

@Echo Off 

Set "SrcDir=%UserProfile%\Desktop\New\Interest\f2" 
Set "Mask=*.txt" 
Set "Line#=26" 
Set "LOfs=23" 
Set "Len=11" 

If /I Not "%CD%"=="%SrcDir%" Pushd "%SrcDir%"2>Nul&&(Set _=T)||Exit/B 

For /F "Tokens=1-2* Delims=:" %%A In ('FindStr/N "^" "%Mask%" 2^>Nul' 
) Do If "%%B"=="%Line#%" If Not "%%~C"=="" (Set "Line=%%C" 
    SetLocal EnableDelayedExpansion 
    If Not "!Line:~%LOfs%,%Len%!"=="" (
     If Not Exist "!Line:~%LOfs%,%Len%! - %%A" (
      Ren "%%A" "!Line:~%LOfs%,%Len%! - %%A")) 
    EndLocal) 

If "_"=="T" PopD 
+0

任何人都可以帮助Compo的脚本我想通过**!行:〜%LOfs%,%Len%!**到一个变量,以检查文本是否有/应该由空间替换,但当我说** Set str =“!Line:〜%LOfs%,%Len%!”**然后** ECHO%str%**我得到输出** ECHO关闭。**。如果我** ECHO“!行:〜%LOfs%,%Len%!”**我得到预期的输出。所有帮助赞赏。谢谢 – jaburmester

+0

这在技术上会是一个不同的问题。我建议您将您所喜欢的答案标记为正确,然后针对您的新要求开始一个新问题。 – Compo

0

这种方法不需要findstr.exe也不切换setlocal/endlocal,所以它应该跑得更快。此外,它避免重新处理任何已更名的文件,将for %%A改为for /F并结合dir命令。

@Echo off 
SetLocal EnableDelayedExpansion 

cd "C:\Documents and Settings\John\Desktop\New\Interest\f2" 
Set /A Line#=26, LOfs=24 -1, Len=34 - LOfs 

For /F "delims=" %%A in ('dir /A-D /B *.txt') do (

    rem Read the desired line from this file 
    (for /L %%i in (1,1,%Line#%) do set "Line=" & set /P "Line=") < "%%A" 

    if defined Line ECHO Ren "%%~fA" "!Line:~%LOfs%,%Len%! - %%A" 

) 

还要注意的是,当这个批处理文件结束当前目录自动恢复到当前的一个时被执行setlocal命令,则不需要这样pushd/popd命令要么。

+0

当然,你可以避免切换延迟扩展,但如果文件名包含'!',它现在将失败。另外,在我的手中,FINDSTR解决方案在找到第26行时比在SET/P中使用FOR/L要快大约5倍。 – dbenham

相关问题