【问题标题】:How to diff directories over ssh如何通过 ssh 区分目录
【发布时间】:2014-01-07 10:22:23
【问题描述】:

我正在尝试递归地将本地主机中的目录与远程 linux 机器中的目录进行比较。但是,当我执行下一个命令时:

diff -r 'ssh admin@10.0.0.10:/home/admin' /home/admin

这样说是行不通的:

diff: ssh admin@10.0.0.10:/home/admin: 没有那个文件或目录

递归比较目录内容的正确方法是什么?

提前致谢

【问题讨论】:

标签: linux shell


【解决方案1】:

如果你不需要比较文件中的细节,只需获取目录/文件名的差异,然后试试这个:

(注意:需要设置“无密码SSH登录”,详情请查看此网址:http://www.linuxproblem.org/art_9.html

diff <(ssh admin@10.0.0.10 ls -R /home/admin) <(ls -R /home/admin)

【讨论】:

  • 当 ssh 要求输入密码时,由于第二个操作符
  • 您需要先为 SSH 会话设置非密码
  • 我更新了答案,请查看此网址linuxproblem.org/art_9.html
  • 请注意,使用ls 可能会遇到一些与使用ls 驱动for 循环(why for i in $(ls *.mp3) - is wrong)相同的限制和问题,尽管进程替换会捕获其中的大部分
  • ls 格式在机器上可能会有所不同。因此,您应该确保每个文件都出现在新行中:ls -1R。另请注意,如果基本路径(此处为 /home/admin)不同,这将无法正常工作。
【解决方案2】:

尝试使用带有“-n”选项的“rsync”,它只是进行“试运行”并告诉你它会做什么。

【讨论】:

  • -c 将告诉 rsync 查看校验和,而不仅仅是日期和长度
  • --delete 是必要的。没有它,您将看不到第二台机器上存在的任何文件,但第一台机器上却看不到。确保您有试运行-n 选项。
  • 当然,您还需要-r-a 进行递归,并且不要忘记在目录名称后添加反斜杠(但不要加星号),否则--delete 不会t 返回任何删除。所以你的命令是rsync -e 'ssh -p 22' -azvn --delete admin@10.0.0.10:/home/admin/ /home/admin/
  • 另一个方便的选项:--itemize-changes (-i) 会告诉你每个文件what has changed
  • @FlorianBrucker 建议示例:rsync --itemize-changes --dry-run -r -c downloads/ user@192.168.1.2:/home/user/downloads/
【解决方案3】:

您可以通过sshfs挂载远程目录,然后您可以使用diff -r来比较两个目录。

或者,您可以在两台机器上运行类似的find 命令来打印文件树(例如文件名、大小和日期),然后使用diff 比较两者的输出。当然,这不会比较文件内容:

diff <(ssh host find /home/admin -printf '"%8s %P\n"') \
     <(find /home/admin -printf '%8s %P\n')

注意ssh 调用中 printf 格式字符串的双引号。 ssh 中继删除了一层。

【讨论】:

  • 在通过diff 比较它们之前,您可能会发现sort find 命令的输出很有用;在这种情况下,我会使用路径作为输出中的第一个元素:&lt;(find /home/admin -printf "%p %s\n" | sort)
  • 使用 %P 比使用 %p 更好,因此您可以区分每个服务器上不同文件夹中的目录
  • 谢谢@reox,我相应地改变了我的答案。实际上,我通常在 (cd dir; find . -printf …) 中使用它,在这种情况下,使用 %p%P 没有任何区别。就是这样。
  • +1 表示 sshfs 的提示,允许在 phpStorm 或其他部署工具等 IDE 中使用挂载的目录
  • @WolfgangBlessen 在任何情况下请记住 sshfs 是一个通过网络的文件系统,并且(基本上)简化为一个用户,因为在远程主机上所做的任何事情都是通过设置底层 ssh 连接的用户。这些限制有时会导致问题,因为某些特殊的文件系统功能可能无法在 sshfs 中正确实现,而像 IDE 之类的工具可能依赖于这些功能。然而,根据我的经验,这些情况极为罕见。大多数问题都源于网络中断(但任何网络解决方案都可能遇到)。
【解决方案4】:

对于下面的所有示例,空文件夹无关紧要。

如果ssh 不需要密码并且您想查看文件

diff -y -W250 \
  <(ssh user@host1 "find /jbossas/modules -type f | xargs -I{} md5sum {} | sort -k2")
  <(ssh user@host2 "find /jbossas/modules -type f | xargs -I{} md5sum {} | sort -k2")

如果ssh不需要密码,而你只是想知道文件夹是否相同

diff -y -W250 \
  <(ssh user@host1 "find /jbossas/modules -type f | xargs -I{} md5sum {} | sort | md5sum") \
  <(ssh user@host2 "find /jbossas/modules -type f | xargs -I{} md5sum {} | sort | md5sum")

如果ssh需要密码

  • 安装sshpass
  • 在 PASS 变量中安全地接收您的密码(密码将在 60 秒内清除):echo -n "Password: "; IFS= read -rs PASS &lt; /dev/tty; trap 'unset PASS; echo "PASS has been cleared"; trap - USR1' USR1; { sleep 60; kill -USR1 $$; } &amp;

所以...

diff -y -W250 \
  <(sshpass -p "$PASS" ssh user@host1 "find /jbossas/modules -type f | xargs -I{} md5sum {} | sort | md5sum") \
  <(sshpass -p "$PASS" ssh user@host2 "find /jbossas/modules -type f | xargs -I{} md5sum {} | sort | md5sum")

如果远程主机上需要sudo

diff -y -W250 \
  <(ssh user@host1 "echo \"$PASS\" | sudo -S find /jbossas/modules -type f | xargs -I{} md5sum {} | sort | md5sum") \
  <(ssh user@host1 "echo \"$PASS\" | sudo -S find /jbossas/modules -type f | xargs -I{} md5sum {} | sort | md5sum")

你可以合并选项。

我推荐icdiff而不是diff,但diff就足够了。

【讨论】:

    【解决方案5】:

    如果您需要 GUI,我发现 krusader 对于此类任务非常有用。 更多详情请见https://www.linux.com/news/synchronize-directories-komparator-and-kdiff3http://krusador.org

    example folder compare

    【讨论】:

      猜你喜欢
      • 2013-11-05
      • 2017-02-26
      • 1970-01-01
      • 2019-09-25
      • 2016-02-25
      • 2014-02-24
      • 2013-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多