我有一个源目录,例如 / my / source / directory / 和一个目标目录,例如 / my / dest / directory / ,我想用一些镜像约束
所以
/my/source/directory/1/foo.txt -> /my/dest/directory/source/directory/1/foo.txt
/my/source/directory/2/3/bar.txt -> /my/dest/directory/source/directory/2/3/bar.txt
我已经将以下命令行一起攻击但看起来有点难看,有人能做得更好吗?
find /my/source/directory -ctime -2 -type f -printf "%P\n" | xargs -IFILE rsync -avR /my/./source/directory/FILE /my/dest/directory/
如果您认为我应该自己添加此命令行作为答案,请发表评论,我不想因为声誉而贪婪。
答案 0 :(得分:5)
这与(封闭式)问题非常相似:Bash scripting copying files without overwriting。我给出的答案引用了其他答案中提到的“find | cpio
”解决方案(减去时间标准,但这是'相似'和'相同'之间的差异),并且还概述了使用GNU'tar'的解决方案。 / p>
当我在Solaris上测试时,GNU tar和(Solaris)cpio都无法保留ctime设置;实际上,我不确定是否有办法做到这一点。例如,touch
命令可以设置atime或mtime或两者 - 但不能设置ctime。 utime()
系统调用也只接受mtime或atime值;它不处理ctime。所以,我相信如果你找到一个保留ctime的解决方案,那么这个解决方案很可能是特定于平台的。 (奇怪的例子:破解磁盘设备并编辑inode中的数据 - 不可移植,需要提升权限。)但是,重读这个问题,我发现'保留ctime'不是要求的一部分(phew);它只是文件是否被复制的标准。
我认为'cd
'操作是必要的 - 但是它们可以完全本地化到脚本或命令行,但是如引用的问题和下面的命令行所示,其中第二个假设GNU tar。
(cd /my; find source/directory -ctime -2 | cpio -pvdm /my/dest/directory)
(cd /my; find source/directory -ctime -2 | tar -cf - -F - ) |
(cd /my/dest/directory; tar -xf -)
不使用chdir()
(又名cd
),您需要专门的工具或选项来处理动态路径名的操作。
如Adam Jaes所述,GNU特定的“find -print0
”和“xargs -0
”非常强大有效。有趣的是,GNU cpio
可以选择处理“find -print0
”的输出,即“--null
”或其缩写形式“-0
”。因此,使用GNU find
和GNU cpio
,安全命令是:
(cd /my; find source/directory -ctime -2 -print0 |
cpio -pvdm0 /my/dest/directory)
注意:这不会覆盖备份目录下的预先存在的文件。为-u
命令添加cpio
。
同样,GNU tar
支持--null
(显然没有-0
短格式),也可以使用:
(cd /my; find source/directory -ctime -2 -print0 | tar -cf - -F - --null ) |
(cd /my/dest/directory; tar -xf -)
使用null终止符对GNU处理文件名非常聪明并且是一项有价值的创新(尽管我最近才意识到这一点,因为SO的礼貌;它已经在GNU tar中使用了至少十年)。
答案 1 :(得分:3)
您可以使用复制传递模式-p尝试cpio。我通常使用它覆盖所有(-u),创建目录(-d),并维护修改时间(-m)。
find myfiles | cpio -pmud target-dir
请记住,find应该生成相对路径名,这不符合您的绝对路径标准。这种冷当然是使用cd“解决”,你也不喜欢(为什么不呢?)
(cd mypath; find myfiles | cpio ... )
括号将生成子shell,并将状态更改(即目录切换)保持为本地。您还可以定义一个小程序来抽象出“丑陋”。
答案 2 :(得分:1)
如果你正在使用find总是使用-print0并通过xargs -0管道输出;几乎总是如此。如果您使用find的默认换行符终结符输出,则名称中带有空格的第一个文件将使脚本生效。
我同意所有其他海报 - 如果可以,请使用cpio或tar。它会做你想要的,省去麻烦。
答案 3 :(得分:0)
另一种方法是使用焦油, (cd $ SOURCE; tar cf - 。)| (cd $ DESTINATION; tar xf - )
修改: 啊,我错过了关于保留CTIME的一点。我相信tar的大多数实现都会保留mtime,但如果保留ctime很关键,那么cpio确实是唯一的方法。
此外,一些tar实现(GNU tar为1)可以根据atime和mtime选择要包含的文件,虽然看似不是ctime。
答案 4 :(得分:0)
#!/bin/sh
SRC=/my/source/directory
DST=/my/dest/directory
for i in $(find $SRC -ctime -2 -type f) ; do
SUBDST=$DST$(dirname $i)
mkdir -p $SUBDST
cp -p $i $SUBDST
done
我想,因为你想要包含“它来自哪里”,你将使用不同的源目录。只需更换SRC = / my / source /目录,SRC = $ 1
即可修改此脚本以将源目录作为参数。编辑:删除多余的if语句。
当文件名有空格时不起作用。
答案 5 :(得分:0)
echo“请输入源DIR的完整路径(以/开头,以/结尾):” 阅读spath
echo“请输入目的地位置的完整路径(以/开头,以/结尾):” 读dpath
SI = echo "$spath" | awk -F/ '{print NF-1}'
for find $spath -type f -print
中的fname
做
CDIR = echo $fname | awk -F/ '{ for (i='$si'; i<NF; i++) printf "%s/", $i; printf "\n"; }'
如果[$ cdir];然后
如果[! -d“$ dpath $ cdir”];然后
mkdir -p $ dpath $ cdir
科幻
网络
cp $ fname $ dpath $ cdir
完成