使用通配符路径重命名文件

Posted

技术标签:

【中文标题】使用通配符路径重命名文件【英文标题】:Rename Files using wildcard paths 【发布时间】:2016-12-19 01:58:21 【问题描述】:

最近我开始工作,我的第一个任务是编写一个批处理文件,它会自动将文件名更改为带有原始文件结尾的 filename_date。 为此,您应该能够将路径写入文本文件(例如paths.txt),并且当您启动程序时,它应该从那里获取任何行(=path->file)并重命名它。 我让它在我的电脑上安静地工作,但是当我把它交给测试时,他们要求使用通配符Z:\Path\*.* 成为可能。 我当前的代码如下所示:

@echo off
setlocal EnableDelayedExpansion
cd %~dp0    

For /F "tokens=*" %%m in (paths.txt) do (

set path=%%~dpm
set name=%%~nxm

pushd "!path!"
dir

For /r !path! %%f in (!name!) do (

set path=%%~dpf
set name=%%~nf
set ending=%%~xf
set datsave=%%~nxf

set "name=!name!_"
set "name=!name!!date:~6,4!"
set "name=!name!!date:~3,2!"
set "name=!name!!date:~0,2!"

set "name=!name!!ending!"

copy "!datsave!" "!name!"

del "!datsave!"
cls
popd
)

)

我知道其中很多可能更容易、更高效,但这是我的第一个批处理项目,除了通配符问题外,我很高兴。 所以一个例子是: C:\Some\Path\*.*

这一行将在paths.txt 中。 随着分裂

set path=%%~dpf
set name=%%~nf
set ending=%%~xf
set datsave=%%~nxf

我得到以下信息:

path: C:\Some\Path
name: C:\Some\Path
ending: -empty-
datsave: C:\Some\Path

因为 name 设置为第一个 FOR 循环开始处的路径。但如果我不使用通配符,这似乎可行。

现在的问题是:为什么会发生这种情况,我该如何摆脱它?还是我只是使用了错误类型的通配符?

再说一遍:这是我第一次使用批处理,所以它可能很简单;)

【问题讨论】:

很好的尝试已经!您必须使用批处理来执行此操作吗? 谢谢 :) 不幸的是。我不知道原因,但是当我的老板说去批量时,我必须;) 【参考方案1】:

好的,我发现了 2 个问题,现在它可以工作了

set name=%%~nxm 计算通配符。即使名称是*.txt,它也会返回bar.txt。 我用基本名称计算代替了它:set name=!name:*\=! 完成了足够多的时间(不是很微妙,但是批处理文件迫使我们做这样的事情),它保留了通配符

另一个问题是for /R loop:在pushd之后,参数必须是.,否则不会被扫描。

最后一个次要的:使用rename 而不是copy 加上delete。它保留了文件时间并且非常快。复制然后删除大文件可能需要很长时间。

@echo off

set DEPTH=20
setlocal EnableDelayedExpansion
cd %~dp0    

For /F %%m in (paths.txt) do (

set pth=%%~dpm
set z=%%m
set name=!z!

rem brutal basename. We cannot break the inner loop or
rem it would break the upper loop too
for /L %%I in (1,1,%DEPTH%) do set name=!name:*\=!
rem but we can check if it is really a basename
set chkname=!name:*\=!
if not !chkname!==!name! ( echo please increase DEPTH value
pause
exit /B)

rem set name=%%~nxm
pushd "!pth!"
For /r . %%f in (!name!) do (
set pth=%%~dpf
set name=%%~nf
set ending=%%~xf
set datsave=%%~nxf

set "name=!name!_!date:~6,4!!date:~3,2!!date:~0,2!!ending!


echo renaming "!datsave!" to "!name!"
rem ren "!datsave!" "!name!"

popd
)

)
paths.txt 只包含一行 C:\full\path\to\test\*.txt 我的test 目录包含 2 个文本文件和 1 个其他文件

输出:

renaming "bar.txt" to "bar_20160812.txt"
renaming "foo.txt" to "foo_20160812.txt"

(只需取消注释 ren 行即可完成工作)

【讨论】:

哇,非常感谢!对其进行了测试,它仍然适用于完整路径,但是这一行:C:\foo\bar\*.* 被完全忽略...如果我设置超时以查看程序中内置的回声,我可以看到该路径完全被排除在进度之外,即使它正确地放入了paths.txt。有什么想法吗? 编辑:它不会被忽略!看起来他更改了目录,但随后没有继续前进并进入给定的下一个路径。 事实上,他将 name 设置为没有驱动器号的路径,推送目录,正确显示它然后不继续... ~nx 修饰符的伟大发现!但是有一个问题:set name=!z:*\=! 删除了直到 first 反斜杠的所有内容,所以 C:\foo\bar\*.* 变为 foo\bar\*.*... 我建议 not 使用变量 @ 987654342@,因为这是系统保留... @aschipfl:我想你会喜欢我做的愚蠢的事情,而不是双变量扩展:for /L %%I in (1,1,20) do set name=!name:*\=! 效果很好。【参考方案2】:

Weeeeell 首先再次感谢@Jean-François Fabre 和@aschipfl 对我的耐心:) 在第二个批处理文件的提示之后,我不得不测试一些东西,因为并非一切都很好,但现在一切都很好!

主文件代码:

@echo off
setlocal EnableDelayedExpansion
cd %~dp0
set DEPTH=20

For /F %%m in (paths.txt) do (
pause
set pth=%%~dpm

  REM pushd !pth!
  REM set origpth=!cd!
  REM popd

set z=%%m
set name=!z!

For /L %%i in (1,1,%DEPTH%) do set 
name=!name:*\=!
set chkname=!name:*\=!
if not !chkname!==!name! ( echo depth to small
pause
exit /B)

rem set name=%%~nxm
pushd "!pth!"

For /r . %%f in (!name!) do (

pushd %~dp0
call renamefiles.bat %%f REM "!origpth!"
popd
)

)

以及子文件的代码:

@echo off   

  REM set pth=%~dp1
  REM set origpth=%2
  REM set origpth=%origpath:"=%\

  REM If !pth!==%origpth% (

set path=%~dp1
set name=%~n1
set ending=%~x1
set datsave=%~nx1

pushd !path!

set "name=!name!_!date:~6,4!!date:~3,2!!date:~0,2!!ending!"

pause

echo renaming "!datsave!" to "!name!"
rem "!datsave!" "!name!"

cls
popd

  REM )

编辑:经过一番测试后,我想,子文件夹也包括在内!我在标有 REM 和两个额外空格的两个代码中添加了额外的代码。取出那些 REM,重命名时程序将不再包含子文件夹:)

【讨论】:

以上是关于使用通配符路径重命名文件的主要内容,如果未能解决你的问题,请参考以下文章

用Python查找某文件夹的文件名称,并对文件名进行更改的库名称是啥?

linux下怎么批量重命名这些文件

如何在 Linux 中批量移动复制追加和重命名文件

关于DOS下的MOVE命令..

Linux 权限和目录更改移除更换目录列出目录内容使用通配符移动重命名

在dos中,包含@的文件可以被重命名吗?不能的话,怎么办?谢谢!在线等!