假设您有两个目录,例如/long_path_1
和/long_path_2
(可能有空格),您知道它们几乎相等,例如,因为您之前运行过diff -rq --no-dereferences /long_path_1 /long_path_2
并且发现只有细微的差异(举一个具体的例子,如果碰巧是您比较的目录.cache
,则还有一些其他点文件存在于$HOME
但不存在于中/mnt/username
)。您还知道许多相同全路径、相同内容文件的某些修改时间不同,并且目录结构中的某些目录也不同(例如,因为许多年前您有点粗心,不是通过cp -auv
而是通过传输了内容cp
,或者从档案中解压了一些文件而没有告诉档案程序正确设置文件时间,或者因为文件在不同的文件系统或通过之间传输,scp
并且高精度丢失了)。在两个相同的全路径、相同的内容文件中,时间最早的文件可能位于任一侧;它可能位于下面/long_path_1/
或下面/long_path_1/
;您不知道。
如果你必须以非递归方式执行任务,你可以运行类似
diff -q --no-dereference "/long_path_1/some subdirectories/file or directory" "/long_path_2/some subdirectories/file or directory"
确保文件确实相等,如果相等,请查看输出
ls -la --full-time "/long_path_1/some subdirectories/file or directory" "/long_path_2/some subdirectories/file or directory"
然后手动比较时间,然后发出
touch -r "/long_path_1/some subdirectories/file or directory" "/long_path_2/some subdirectories/file or directory"
(如果第一个男人年纪较大)或
touch -r "/long_path_2/some subdirectories/file or directory" "/long_path_1/some subdirectories/file or directory"
(如果第二个男人年纪较大)
如何以递归方式执行此操作,以便在两个副本中(而不是仅在一个副本中)获取最早的已知修改时间?我考虑类似
cd "/long_path_1"
find . -type f -exec bash -c "if [[ -f \"{}\" && -f \"/long_path_2/{}\" ]]; then if ( cmp -s \"{}\" \"/long_path_2/{}\" ) then if [[ \"{}\" -ot \"/long_path_2/{}\" ]]; then touch -r \"{}\" \"/long_path_2/{}\"; else if [[ \"/long_path_2/{}\" -ot \"{}\" ]]; then touch -r \"/long_path_2/{}\" \"{}\"; fi; fi; fi; fi" \;
find . -type l -exec bash -c "if [[ -h \"{}\" && -h \"/long_path_2/{}\" ]]; then if (test $(readlink \"{}\") = $(readlink \"/long_path_2/{}\")) then if (find \"/long_path_2/{}\" -prune -newer \"{}\" -printf 'a\n' | grep -q a) then touch -h -r \"{}\" \"/long_path_2/{}\"; else if (find \"{}\" -prune -newer \"/long_path_2/{}\" -printf 'a\n' | grep -q a) then touch -h -r \"/long_path_2/{}\" \"{}\"; fi; fi; fi; fi" \;
find . -type d -exec bash -c "if [[ -d \"{}\" && -d \"/long_path_2/{}\" ]]; then if (cmp -s <(ls -Al --full-time \"{}\") <(ls -Al --full-time \"/long_path_2/{}\") then if [[ \"{}\" -ot \"/long_path_2/{}\" ]]; then touch -r \"{}\" \"/long_path_2/{}\"; else if [[ \"/long_path_2/{}\" -ot \"{}\" ]]; then touch -r \"/long_path_2/{}\" \"{}\"; fi; fi; fi; fi" \;
但它确实很麻烦(因为它要运行目录结构三次并为每个文件生成一个 bash),而且我不知道如何做正确的事情,尤其是对于符号链接、目录(如何比较它们?)以及到目录的符号链接。
答案1
如果这只是一次性修复现有文件时间,那么rsync -rct
将使其变得简单得多(r
递归地仅比较文件c
hecksum,t
如果不同则从源更新 ime 戳)。
您仍需说明哪个源文件夹是要从中复制时间的“较旧”文件夹。尝试使用rsync -vvrctn /src /dst
仅转储时间戳不同的文件列表,以便您可以查看。
最后一步“仅处理较旧的文件”在 bash 中要困难很多倍,而且(正如您所发现的)时间戳对于大多数备份/恢复目的来说并不真正可靠。如果您预计需要定期回滚+同步文件,那么您可能需要研究源代码/版本控制工具。