当我在USB密钥上执行rsync时,如何替换冒号?

我想在USB密钥上备份我的邮件目录。 但是,我的IMAP有一个奇怪的命名约定,包括冒号(:)字符。 由于USB采用窗口格式,因此rsync无法创建这些文件。 有没有办法在运行rsync时用下划线替换冒号? (或者与其他工具进行相同的同步?)

我在评论中澄清了几点:

  • 这是最糟糕的情况备份,我希望能够在没有安装任何东西的情况下在Windows机器上读取它。
  • 我得到了很多保持不变的数据。 如果我有一个只复制较新文件的工具,那么我节省了很多时间。
  • 我不是在寻找rsync的重写。 我正在寻找一种可以开箱即用的现有工具。

谢谢

使用rdiff-backup而不是普通rsync。 它将自动检测并替换目标磁盘上不支持的字符,并将它们恢复为恢复到unix文件系统时的状态。 它生成一个解压缩的目录,看起来就像原点和一个额外的元数据目录。

最直接的方法是利用文件系统层来转换文件名。 从Ubuntu 12.04开始,有一个FUSE文件系统可以将文件名转换为Windows VFAT支持的名称: fuse-posixovl 安装fuse-posixovl

sudo mount.posixovl /media/sdb1 chown guillaume /media/sdb1 rsync -au ~/mail /media/sbd1/ 

或者为了避免需要root访问权限:

 mkdir ~/mnt /sbin/mount.posixovl -S /media/sdb1 ~/mnt rsync -au ~/mail ~/mnt/ 

VFAT不接受的文件名中的字符编码为%(XX) ,其中XX是hex数字。 从POSIXovl 1.2.20120215开始,请注意像%(3A)这样的文件名被编码为自身,并将被解码为: ,如果您的文件名包含格式为%(XX)子字符串,则存在冲突的风险。

请注意POSIXovl不能处理太长的文件名。 如果编码名称不适合255个字符,则无法存储该文件。

POSIXovl将unix权限和所有权存储在名为.pxovl.FILENAME文件中。


以下bash≥4脚本将~/mail/foo:bar复制到/media/usb99/mail/foo_bar ,对于~/mail下的所有文件也是如此。 将跳过目标树中已存在且不早于源的文件。

 #!/bin/bash set -e shopt -s dotglob globstar for source in "$HOME"/mail/**/*; do target=/media/usb99/${source#"$HOME"/} target=${target//:/_} if [[ -d $source ]]; then mkdir -p -- "$target" elif [[ $target -ot $source ]]; then cp -p -- "$source" "$target" fi done 

这个脚本在zsh下工作,稍作修改:用setopt dot_glob替换shopt -s dotglob globstar ,用[[ ! -e $target || $target -ot $source ]]替换[[ $target -ot $source ]] [[ ! -e $target || $target -ot $source ]] [[ ! -e $target || $target -ot $source ]]


这是一个zsh双线(如果算上自动加载,则为三个)。 它更短,但相当先进,不太可读。

 autoload zargs zmv zargs -- ~/mail/**/*(/e\''REPLY=/media/usb99/${${REPLY#$HOME/}//:/_}'\') -- mkdir -p -- zmv -C -Q -o -pu '~/mail/(**/)(*)(.)' '/media/usb99/mail/${1//:/_}${2//:/_}' 
  • zargs行等同于mkdir -p ~/mail/**/*(…) ,但如果目录名的累积长度太长则不会弹出。 该行根据需要创建目标目录。
  • ~/mail/**/*(/)扩展到~/mail下的所有目录(目录仅由于(/)结尾)。
  • (/e\''…'\')仅选择目录并进一步执行’…’中的代码以转换存储在REPLY变量中的每个文件名。
  • ${${REPLY#$HOME/}//:/_}删除与源目录对应的前缀,并更改为: _
  • zmv -C将与其第一个操作数(zsh模式)匹配的每个文件复制到通过扩展其第二个操作数获得的文件名。
  • -o -pu表示将-pu传递给cp实用程序,以便保留权限并仅复制更新的文件。 (我们可以告诉zsh执行更新检查;它会更快一点,但更加神秘。)
  • (.)仅选择常规文件。 -Q表示这将被解析为glob限定符而不是. 括号周围表示子表达式。
  • 替换文本中的$1$2匹配括号表达式(**/)* 。 ( **如果在括号中,则将其特殊含义丢失为零或更多子目录级别,除非括号中包含**/ 。)

我最初想过使用pax ,它是一个归档工具(这里打算用于传递模式),它具有文件重命名function(它的-s选项)。 但是, -s-u选项不能一起工作( pax的POSIX定义字面上说-u必须检查目标树中的同名文件,而不是-s转换的文件名; pax实现在Ubuntu中遵循规范,而不是有用的)。 它仍然可以利用它来重命名硬链接,然后将硬链接(使用rsync -aupax -rw -pp -u )复制到其他媒体,但感觉比它的价值更麻烦。

 cd ~/mail mkdir -p /media/usb99/mail pax -rw -l -pp -s '!:!_!g' . ../mail.colonless rsync -au ../mail.colonless/ /media/usb99/mail/ 

我用我的USB记忆棒和移动USB磁盘做的是用2个分区分区:FAT32和ext4分区。 第一个我可以用来与非Linux用户交换数据,第二个用于我个人用于我的Ubuntu系统(也许可以与其他linux用户交换)。 在ext4分区上,您不会遇到“:”问题。

您可以使用tar来创建存档。 这样您就不必更改名称,并可以将其保存到您想要的任何文件系统中。