如何使用rsync而不是批量进入for循环

How to use rsync instead of move in for loop in batch

在路径 U:\0012* 中的每个子文件夹中,我创建了一个示例文件夹并将文件从相应的子文件夹移动到示例文件夹。

FOR /d %%A IN (U:[=10=]12\*) DO mkdir %%~A\example & move %%~A\*.* %%~A\example\ 

我想尝试的是使用 rsync 命令而不是 move

 FOR /d %%A IN (U:[=11=]12\*) DO 
C:\cygwin\bin\rsync.exe -av -h --progress --checksum "/cygdrive/U/0012/%%A/*.*/" "/cygdrive/U/0012/%%A/EXAMPLE/" 

脚本因语法错误而自行关闭。是否可以在for循环中使用rsync?

rsync 可以在 for 循环中 运行。下面是将所有文件从目录移动到同一目录中的 "EXAMPLE" 目录的示例代码。

#!/bin/sh for d in ~/Desktop/a/*; do rsync -rav -h --progress --checksum $d/*.* $d/EXAMPLE/ done

将以上内容保存在 .sh 文件中,然后 运行 该文件。上面的代码将遍历 ~/Desktop/a/ 目录中的所有子目录,并在每个子目录中创建 EXAMPLE 目录,并将所有文件复制到 EXAMPLE 目录。

我认为您遇到了 "Windows World" 和“Unix World”的冲突。

您尝试使用自然 Unix 工具 rsync 进行的操作是使用批处理文件路径进行复制并将其放入 rsync 路径。这行不通。

我将剖析您的代码:

在这部分中,您仍在 "Windows world" 中,您正在使用 FOR 以 windows 方式 FOR /d %%A IN (U:[=18=]12\*) DO 通过 U:[=17=]12\* 路径循环。

您已尝试 "help" rsync 使用 unix 样式路径 /cygdrive/U/0012/,但变量 %%A 包含 windows 样式路径!

C:\cygwin\bin\rsync.exe -av -h --progress --checksum "/cygdrive/U/0012/%%A/*.*/" "/cygdrive/U/0012/%%A/EXAMPLE/"

您遇到的错误可能类似于:

The source and destination cannot both be remote. rsync error: syntax or usage error (code 1) at main.c(1292) [Receiver=3.1.2]

如何解决这样的错误?

首先要说的是,我正在为 linux 工具使用 MSYS 环境。我已经在我的本地文件上测试过了。

批处理文件中,您可以按以下方式进行:

@echo off
FOR /d %%A IN (U:[=11=]12\*) DO (
    SET "copy_path=%%A"
    C:\msys64\usr\bin\cygpath.exe -u %copy_path% > tmp_file.tmp
    SET /P unix_path=<tmp_file.tmp
    DEL tmp_file.tmp
    ECHO "%unix_path%"
    C:\msys64\usr\bin\rsync.exe -av -h --progress --checksum --remove-source-files "%unix_path%" "%unix_path%/EXAMPLE/"
    )
)

脚本采用 Window 路径 C:\prg\PowerShell\test\SO\test1\* 然后它使用 cygpath.exe 将路径转换为 ​​unix 样式路径并将其保存到临时文件 (tmp_file.tmp).然后它从临时文件中读取路径到 unix 变量 %unix_path% 中,然后在 rsync.exe 中使用。

注意:因为有人已经链接了如何使用 rsync 移动文件。我只会说明选项。您必须添加 --remove-source-files,它会在传输后删除文件。

** 编辑 **

  • 我想我现在明白你的意思了。现在 rsync 应该真的像移动一样。唯一的区别是如果目录 example 存在,它会与文件一起复制。 (如果没有创建它并将文件移动到那里)-我认为这是查看 mkdir && move.
  • 时的初衷

我做了什么?

ENABLEDELAYEDEXPANSION 正确读取文件中的变量(在最后一次读取之前)

"!unix_path!/" 最后一个反斜杠对于 rsync 的正确运行非常重要。

我已经在我的电脑上测试了脚本,对我来说它可以正常工作。

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

FOR /D %%A IN (C:\prg\t\*) DO (
    ECHO %%A
    SET "copy_path=%%A"
    C:\msys64\usr\bin\cygpath.exe -u !copy_path! > tmp_file.tmp
    SET /P unix_path=<tmp_file.tmp
    DEL tmp_file.tmp
    ECHO "!unix_path!"

    ECHO C:\msys64\usr\bin\rsync.exe -av --progress --checksum --remove-source-files "!unix_path!/" "!unix_path!/example/"
    C:\msys64\usr\bin\rsync.exe -av --progress --checksum --remove-source-files "!unix_path!/" "!unix_path!/example/"
)

** 第二次编辑 ** 使用 rsync

不会删除空目录

我不建议在一次操作中使用 --remove-files && --delete 选项,因为 rsync 可能会失败。您可以在此处阅读更多内容 superuser.com or unix stack exchange or even server fault

我会简单地使用已经写好的解决方案:How to delete empty folders using windows command prompt?(我说的是解决方案(所有功劳都归功于作者),它也包含带空格的目录):

for /f "usebackq delims=" %%d in (`"dir /ad/b/s | sort /R"`) do rd "%%d"

最终脚本将如下所示:

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

FOR /D %%A IN (C:\prg\t\*) DO (
    ECHO %%A
    SET "copy_path=%%A"
    C:\msys64\usr\bin\cygpath.exe -u !copy_path! > tmp_file.tmp
    SET /P unix_path=<tmp_file.tmp
    DEL tmp_file.tmp
    ECHO "!unix_path!"

    ECHO C:\msys64\usr\bin\rsync.exe -av --progress --checksum --remove-source-files "!unix_path!/" "!unix_path!/example/"
    C:\msys64\usr\bin\rsync.exe -av --progress --checksum --remove-source-files "!unix_path!/" "!unix_path!/example/"
)
REM To delete empty directories - the windows way
REM save current directory to stack
pushd 

cd C:\prg\t
REM Will delete all empty directories (subdirectories) at current path
for /f "usebackq delims=" %%d in (`"dir /ad/b/s | sort /R"`) do rd "%%d"

REM return to saved directory
popd