[英]Move files to a subdirectory
使用一些很大的帮助( 在包含文件的每个目录下创建子目录)我在任何包含 .jpg 照片的目录中添加了一个 \pre 子目录。
我想将任何 .jpg 文件从其当前目录移动到 \pre 子目录中。 我试过的脚本是:
FOR /R c:\temp %G IN (*.JPG) DO pushd %~dpG && if exist *.jpg move *.jpg pre\ && popd
该脚本移动了 .jpg 文件。 问题是脚本移动文件然后跟随到 \pre 目录并尝试再次移动。
pre 目录是使用第一段中链接的脚本创建的。
例如,目录 A\B\C 被处理为 A\B\C\pre。 此脚本扫描 A/B/C 并将 .jpgs 移动到 \A\B\C\pre。 然后它沿着目录树进入 A\B\C\pre 并尝试再次移动 .jpg 文件
下面的脚本呢:
@echo off
rem // Enumerate the directory tree:
for /D /R "C:\TEMP" %%G in ("*") do (
rem // Check whether current directory is not named `pre`:
if /I not "%%~nxG" == "pre" (
rem // Check whether there are files:
if exist "%%~G\*.jpg" (
rem // Create sub-directory called `pre`:
md "%%~G\pre" 2> nul
rem // Move files into the sub-directory:
move "%%~G\*.jpg" "%%~G\pre"
)
)
)
或者直接在命令提示符下:
@for /D /R "C:\TEMP" %G in ("*") do @if /I not "%~nxG" == "pre" if exist "%~G\*.jpg" md "%~G\pre" 2> nul & move "%~G\*.jpg" "%~G\pre"
我建议将此批处理文件用于文件移动任务。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "delims=" %%I in ('dir "C:\Temp\*.jpg" /A-D /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /L /V /C:"\\pre\\" /C:"\\post\\"') do (
if not exist "%%~dpIpre\" md "%%~dpIpre"
move /Y "%%I" "%%~dpIpre\"
)
endlocal
FOR在后台启动另一个命令进程,其中%ComSpec% /c
和指定的命令行作为附加参数附加。 因此,在后台将 Windows 安装到C:\Windows
中执行:
C:\Windows\System32\cmd.exe /c dir "C:\Temp\*.jpg" /A-D /B /S 2>nul | %SystemRoot%\System32\findstr.exe /I /L /V /C:"\\pre\\" /C:"\\post\\"
后台命令进程执行的DIR搜索
/S
在目录C:\Temp
及其所有子目录中/AD
仅用于文件(属性不是目录)*.jpg
/B
以裸格式输出/S
,只是具有完整路径的文件名。 此文件名列表使用重定向运算符|
从后台命令进程的STDOUT (标准输出)重定向。 到查找的FINDSTR的STDIN (标准输入)
/I
而包含不区分大小写的行\pre\
或文字字符串\post\
/V
输出反转结果,即不包含\pre\
或\post\
的行。 因此FINDSTR在这里用作过滤器,以从DIR输出的 *.jpg 文件名列表中获取完整路径,只是那些路径中没有\pre\
或\post\
的文件名,以排除已经存在的 JPEG 文件在名称为pre
或post
的两个子目录之一中。
2>nul
在命令DIR的参数之后,如果在C:\Temp
及其子目录中找不到任何 *.jpg 文件名,则通过将写入STDERR (标准错误)的错误消息重定向到设备NUL来抑制DIR输出的错误消息.
阅读有关使用命令重定向运算符的 Microsoft 文章,了解2>nul
的说明。 重定向运算符>
和|
当 Windows 命令解释器在执行命令FOR之前使用findstr
执行嵌入的dir
命令行并使用在后台启动的单独命令进程时,必须在FOR命令行上使用插入字符^
进行转义,以将其解释为文字字符。
带有选项/F
的FOR捕获由FINDSTR为处理已启动命令进程的STDOUT而编写的所有内容,并在启动的cmd.exe
自行终止后逐行处理此输出。 在这里处理捕获的文件名列表非常重要,并且不要在文件系统返回的另一个文件名之后迭代一个文件名,因为通配符模式匹配的文件 *.jpg 在目录结构中的每次循环迭代期间都会移动. 因此,与 *.jpg 匹配的目录条目在每次循环迭代时都会发生变化,因此需要在移动文件之前将文件名列表加载到内存中。
带有选项/F
的FOR忽略此处未出现的空行。
带有选项/F
的FOR将使用普通空格和水平制表符作为字符串分隔符将每一行拆分为子字符串,并且如果不以默认行尾字符开头,则将仅将第一个空格/制表符分隔的字符串分配给指定的循环变量I
;
在这种情况下,该行将像空行一样被完全忽略。
具有完整路径的文件名不能以;
开头 . 所以默认eol=;
此处不得修改。 但是行拆分行为会适得其反,因为完整的限定文件名可以包含一个或多个空格。 出于这个原因,选项delims=
用于定义字符串分隔符的空列表,它完全禁用行拆分行为。
因此,由DIR输出的每个完整文件名在由FINDSTR过滤掉的路径中不包含\pre\
或\post\
一个接一个地分配给循环变量I
接下来检查当前 JPEG 文件是否存在子文件夹pre
,如果不存在则创建该文件夹。 然后当前的 JPEG 文件被移动到子目录pre
中,并用完全相同的文件名覆盖pre
中的文件。
所以这个批处理文件可以在C:\Temp
上执行多次,因为它会忽略所有子目录pre
和post
中的所有 *.jpg 文件
要了解使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。
dir /?
echo /?
endlocal /?
findstr /?
for /?
if /?
md /?
move /?
setlocal /?
通过在枚举目录之前获取目录列表来解决在新的“pre”目录中执行操作的问题。
使用单行命令执行此操作可能会很好,但这比单行命令中容易执行的操作要复杂一些。
这是一个可以执行此操作的 PowerShell 脚本。 如果您在受支持的 Windows 平台上,则可以使用 PowerShell。 此脚本需要 PowerShell 5.1 或更高版本。 如果您无法访问当前的 PowerShell,可以更改代码以使其正常工作。 如果您对移动正确的文件感到满意,请从mkdir
和Move-Item
命令中删除-WhatIf
。
=== Move-JpegToPre.ps1
$dirs = Get-ChildItem -Directory -Path "C:/src/t"
$extent = 'jpg'
foreach ($dir in $dirs) {
if (Test-Path -Path "$($dir.FullName)/*.$($extent)") {
if (-not (Test-Path -Path "$($dir.FullName)/pre")) {
mkdir "$($dir.FullName)/pre"
}
Move-Item -Path "$($dir.FullName)/*.$($extent)" -Destination "$($dir.FullName)/pre" -WhatIf
}
}
在 cmd.exe shell 中,可以通过以下方式调用它:
powershell -NoLogo -NoProfile -File Move-JpegToPre.ps1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.