【问题标题】:Batch file to tidy-up files per name批处理文件以按名称整理文件
【发布时间】:2019-07-22 09:36:03
【问题描述】:

我有以下文件夹:

Apple_folder
Pear_folder
Tomatoes_folder

Apple_folder 内,我有以下文件:

Extracted-Apple_1.txt
Extracted-Apple_2.txt
Extracted-Pear_1.txt
Extracted-Pear_2.txt
Extracted-Apple_3.txt
Extracted-Tomatoes_1.txt

如何将Extracted-Pear_1.txtExtracted-Pear_2.txtExtracted-Tomatoes_1.txt 移动到它们的相关文件夹中,即在Apple_folder 下保留包含apple 的文件名等

预期的Apple_folder 内容:

Extracted-Apple_1.txt
Extracted-Apple_2.txt
Extracted-Apple_3.txt

我还是批处理脚本的初学者,所以不知道如何进行?

for %%a in (*.txt) do (
   echo %filename%    
   for /f "tokens=* delims=- _" %%f in (%filename%) do (
      if tokens==Pear move Extracted-Pear*.txt   "C:\Users\ABCD\Documents\Pear_folder\"
      if tokens==Tomatoes move Extracted-Pear*.txt "C:\Users\ABCD\Documents\Tomatoes_folder\"
   )

我正在使用此代码尝试重命名文件以避免覆盖目标文件夹中具有相似名称的文件。

setlocal enabledelayedexpansion
set /A counter=0

@echo off
for %%a in (*.txt) do (  
set /A counter+=1
    for /f "tokens=2 delims=-_" %%f in ("%%a") do (
        move Extracted-%%f_*.txt "C:\Users\ABCD\Documents\%%f_folder\Extracted-%%~nf_moved_!counter!.txt"
    )
)

只有一个文件被移动/重命名,然后得到一条错误消息

"Cannot move multiple files to a single file."

【问题讨论】:

  • 提示:使用for 循环迭代文件,使用for /f 在分隔符-_ 处拆分文件名
  • 再次阅读for /f 文档。尤其是看看页面底部的示例。您对tokensdelims 的理解似乎是错误的。
  • 您的括号不平衡。我已对您的代码进行了格式化和缩进,以便您更容易注意到该问题。
  • 感谢@LotPings,我需要做一些研究,因为我以前没有做过这种类型的操作。
  • 感谢@Compo 的帮助。

标签: batch-file


【解决方案1】:

除了 Compo 提到的缺少的) 之外,还有对tokensdelims 工作原理的误解。有关详细信息,请参阅SS64

要使变量filename 工作,您需要delayed expansion,但您可以直接使用for 变量(%%a) 来工作:

@echo off
for %%a in (*.txt) do (
   for /f "tokens=2 delims=-_" %%f in ("%%a") do (
      ECHO move Extracted-%%f_*.txt  "C:\Users\ABCD\Documents\%%f_folder\"
   )
)

tokensdelimiters部分的一些解释:

for /f 循环通过在“分隔符”处将字符串拆分为“令牌”:

tokens=* 告诉for 获取整个字符串,忽略分隔符(简化版本 - 实际上它有点复杂)。

Extracted-Apple_1.txt-_ 分隔,为您提供三个标记:ExtractedApple.txt,第一个标记名为%%f(由您提供),下一个只是命名与以下字母。令牌 2 将是 %%g,令牌 3 将是 %%h

现在变得有趣了:使用tokens=2,您告诉for 只获取第二个令牌(它将转到%%f(!),因为它是第一个(也是唯一一个)返回 令牌)

所以这就引出了上面的"tokens=2 delims=- _"

注意我只是通过回显move 命令来禁用它(用于安全和故障排除)。只有当它按预期工作时,才删除ECHO 以启用move 命令。

编辑以符合“不覆盖”请求:

@echo off
setlocal enabledelayedexpansion
set "counter=0"
for /f "delims=" %%a in ('dir /b *.txt') do (
    for /f "tokens=2 delims=-_" %%f in ("%%a") do call :FileMove "%%a" "%%f"
)
pause
goto :eof

:FileMove
set counter=0
:FileNext
if exist "C:\Users\NABIL\Documents\TESTING\Batch_script\%~2_folder\%~n1_moved__%counter%.txt" (
  set /a counter+=1
  goto :fileNext
)
md "C:\Users\NABIL\Documents\TESTING\Batch_script\%~2_folder\" 2>nul
MOVE "%~1" "C:\Users\NABIL\Documents\TESTING\Batch_script\%~2_folder\%~n1_moved__%counter%.txt"
goto :eof

我将重命名和移动到子程序“外包”,主要是因为我们需要一个goto,这在代码块中是不可能的。我还将你的目标文件命名方案更改为我认为你想要的,但我可能错了 - 所以请检查一下。

【讨论】:

  • 感谢您的帮助。非常感谢您的解释。我运行了它,但它给出了一个错误:_" 在这个时候是意外的..
  • 已编辑。 (这是delims=- _ 的空格 - 我从您的问题中复制/粘贴了它;我们不希望空格作为分隔符 - 如果我们想要它,空格必须是最后一个字符)
  • 删除delims中的空格后就可以使用了。非常感谢您的帮助@Stephan。你是明星!
  • 我只是对 for 循环有一点经验(链接网站底部的 Terry Pratchett 引用无缘无故没有 ;))。
  • 你能说出为什么上面的脚本不起作用吗?谢谢!
【解决方案2】:

setlocal enabledelayedexpansion
set /A counter=0

@echo off
for %%a in (*.txt) do (
    for /f "tokens=2 delims=-_" %%f in ("%%a") do (
set /A counter+=1 
MOVE "%%a" "C:\Users\ADMIN\Documents\TESTING\Batch_script\%%f_folder\Extracted-%%~nf_moved__!counter!.txt"
    )
)
pause

【讨论】:

  • for %%a in (*.txt) 处理(动态)所有*.txt 文件如果您在该过程中创建新的匹配文件,这些文件也可能会被处理。更好:for /f "delims=" %%a in ('dir /b *.txt') do...dir /b *.txt 执行一次,for /f 循环处理其(静态)输出。你也忘了在移动之前检查目的地的存在。
  • 有人可以尝试一下,请告诉我!!
猜你喜欢
  • 2018-01-09
  • 1970-01-01
  • 1970-01-01
  • 2019-07-09
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 2014-02-26
  • 2019-06-08
相关资源
最近更新 更多