【问题标题】:How to use rsync instead of move in for loop in batch如何使用 rsync 而不是批量移入 for 循环
【发布时间】:2018-10-04 17:48:06
【问题描述】:

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

FOR /d %%A IN (U:\0012\*) DO mkdir %%~A\example & move %%~A\*.* %%~A\example\ 

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

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

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

【问题讨论】:

  • 根据您在问题中包含的内容,在我看来,除非源或目标中的至少一个不是“远程”,否则您不能使用 rsync 而不是移动。答案在您的错误消息中,因此请说明您需要什么帮助?
  • 您告诉rsync 递归到目录中。所以你正在创建一个循环操作。您的目标目录也在您的源路径中,因为您使用的是-r 选项。这会创建循环操作。
  • 所以我已经编辑了我的问题,两个目的地都不再遥远了
  • 也许这有帮助? Using rsync to move (not copy) files
  • 你遇到了什么错误?

标签: batch-file for-loop rsync


【解决方案1】:

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

你正在尝试使用rsync,这是一个自然的 Unix 工具,是使用批处理文件路径复制并将其放入 rsync 路径。这行不通。

我会剖析你的代码:

在这一部分中,您仍处于“Windows 世界”中,您正在使用 FOR 以 Windows 方式 FOR /d %%A IN (U:\0012\*) DO 循环通过 U:\0012\* 路径。

您尝试使用 unix 样式路径 /cygdrive/U/0012/ 来“帮助”rsync,但变量 %%A 包含 windows 样式路径!

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

你得到的错误可能是这样的:

源和目标不能都是远程的。 rsync 错误:语法 或 main.c(1292) [Receiver=3.1.2] 处的使用错误(代码 1)

如何解决这样的错误?

首先是说我正在使用MSYS linux 工具环境。我已经在我的本地文件上对其进行了测试。

批处理文件中你可以这样做:

@echo off
FOR /d %%A IN (U:\0012\*) 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/"
    )
)

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

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

** 编辑 **

  • 我想我现在明白你的意思了。现在rsync 应该真的像移动一样。唯一的区别是如果目录example 存在,它会与文件一起复制。 (如果没有创建它并将文件移到那里)-我认为这是查看mkdir &amp;&amp; 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.comunix stack exchange甚至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

【讨论】:

  • 我已经测试了你的解决方案,结果是子文件夹中的所有文件都被删除了,只有子文件夹保持不变
  • @OlegNekhayenko 我不明白你的评论。 “子文件夹中的所有文件都被删除,只有子文件夹保持不变”。怎么可能在删除的同时保持不变?
  • @OlegNekhayenko 看到我的编辑。现在脚本可以正常工作了。
  • 谢谢!!这正是我所需要的。唯一的问题是“删除源文件”命令在删除里面的文件后留下一个文件夹。
  • @OlegNekhayenko 太棒了!由于 rsync 不支持直接删除命令,因此我将使用更多信息编辑帖子。请不要忘记接受并为答案投票 - stackoverflow.com/help/someone-answers
【解决方案2】:

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目录中。

【讨论】:

  • 这如何连接到批处理文件并从内部运行 rsync 工具?
  • 哦,好吧,我没有看到批处理文件标签。
猜你喜欢
  • 1970-01-01
  • 2012-01-27
  • 2021-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-06
  • 2018-12-05
  • 2014-07-18
相关资源
最近更新 更多