我在Linux中有两个目录images和images2具有这种结构:

/images/ad  
/images/fe  
/images/foo  


...和另外4000个文件夹

,另一个就像:

/images2/ad  
/images2/fe  
/images2/foo


...以及其他4000个文件夹

每个文件夹都包含图像,并且images和images2下的目录名称完全相同相同,但是内容不同。然后,我想知道如何将/ images2 / ad的图像复制合并到images / ad,将/ images2 / foo的图像复制合并到images / foo,等等,所有4000个文件夹。.

评论

两个目录中的最终文件名称是否相同?

不,例如在图像/广告中为1.jpg,2.jpg和3.jpg。但是在images2 / ad中是4.jpg和5.jpg

@AmirAliAkbari,我不认为它是重复的-另一个问题基本上是“ MV是否合并?” (答案:否)。这个问题是关于如何合并2个目录层次结构的。

#1 楼

这是rsync的工作。除非您要移动文件而不是复制文件,否则使用shell循环手动执行此操作没有任何好处。

rsync -a /path/to/source/ /path/to/destination


对于您的情况:

rsync -a /images2/ /images/


(注意images2上的斜杠,否则将复制到/images/images2。)

如果两个目录中都存在相同名称的图像,则上面的命令将被覆盖/images/SOMEPATH/SOMEFILE/images2/SOMEPATH/SOMEFILE。如果只想替换旧文件,请添加选项-u。如果要始终将版本保留在/images中,请添加选项--ignore-existing

如果要使用rsync从/images2中移动文件,则可以传递选项--remove-source-files。然后rsync依次复制所有文件,并在完成后删除每个文件。如果源目录和目标目录位于同一文件系统上,则这比移动要慢得多。

评论


..add -P如果您想查看进度。

– Meetai.com
2015年6月16日下午6:00

我要补充一点,即使您确实想移动它们而不是复制它们,在这里使用棘手的shell循环也没有好处-在这种情况下,只需使用rsync,然后使用rm -r / images即可。

–通配符
16年2月7日在8:35

@Wildcard,好吧,这与搬家不太一样。正如吉尔斯指出的,如果他们在相同的fs上,移动要比移动慢得多。而且它需要更多的临时备用空间。

– LarsH
16-6-29在2:11

我还要指出,在每个目录中都包含斜杠非常重要。例如,如果您仅运行rsync -a images images2,它将仅将images2复制到图像中,而不是合并它们。

–凯尔·查利斯(Kyle Challis)
17-10-18在1:28



@ s3cur3哦。从2到(隐式)1.这是不直观的。谢谢,我确定了答案。

–吉尔斯'所以-不再是邪恶的'
19年7月24日在6:55

#2 楼

正如已经发布的,最好的选择当然是rsync。但是,统一也将是完成此工作的出色软件。两者都可以在多个操作系统中使用。

Rsync

rsync沿一个方向从源到目标进行同步。
因此,以下语句

rsync -avh --progress Source Destination


同步从源到目标的所有内容。合并的文件夹位于“目标”中。

-a表示“存档”,并将所有内容从源递归复制到目的地,几乎保留了所有内容。

-v提供更多输出(“详细”)。

-h便于阅读。

-显示执行多少工作的进度。

如果只想使用源文件夹中的较新文件:

rsync -avhu --progress source destination


Unison

unison双向同步。因此,以下语句

unison Source Destination


双向同步两个目录,最终source等于destination。这就像从源到目标执行rsync两次,反之亦然。

有关更高级的用法,请参见手册页或以下网站:


https:/ /www.cis.upenn.edu/~bcpierce/unison/
https://rsync.samba.org/


评论


我要提到的是,正确的文件夹路径应在末尾rsync -avh --progress source / destination /后面加上斜杠,否则源文件夹将在目标文件夹中创建,至少在我的情况下是这样。

–电极
16-10-23在7:12

这对我来说非常有用(文件夹中有斜杠)。谢谢!

– Leopoldo Sanczyk
16年11月2日在22:30

#3 楼

for dir in images2/*; do mv "$dir"/* "images/$(basename "$dir")"; done


使用扩展的glob遍历images2的所有内容(以避免解析ls的问题),然后mv将这些项目的内容添加到images中的匹配条目。使用basename从球形路径剥离前导images2

评论


我知道这确实很老,但是有没有简便的方法可以修改它以仅复制名称中包含特定字符串的文件?就像如果文件名像'* 2160 *'这样的mv

–克里斯·桑德维克(Chris Sandvik)
20 Jan 15'5:38

#4 楼

@ inulinux12,您可以从命令行使用以下一行for循环:注意:这假定没有文件具有相同的名称。

例如:

执行前:

$ for dir in images2/*; do mv "$dir"/* "${dir/2/}"; done


执行后:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2
images/adfoo:
jpg.7
images/fe:
jpg.5
images2:
ad  adfoo  fe
images2/ad:
jpg.3
images2/adfoo:
jpg.6
images2/fe:
jpg.4


评论


不要解析ls的输出。 mywiki.wooledge.org/ParsingLs

– Etan Reisner
2014年8月12日23:48

@EtanReisner谢谢你的建议;尽管考虑到问题中给出的信息,但情况似乎非常狭窄。

–Simply_Me
2014年8月13日在0:01



@Simply_Me虽然通常会很好,但您确实不希望在遇到您不指望的案件时将其炸毁。它可能会导致严重的问题。更不用说它(通常是这种情况)几乎可以用一个简单的glob替换掉。请参阅我的答案作为示例。

– Etan Reisner
14年8月13日在0:04

@Simply_Me方案包括带空格的文件名,这在图像中很常见。

–吉尔斯'所以-不再是邪恶的'
14年8月13日在0:35

@Gilles和@Etan Reisner,谢谢您的投入,我非常感谢!更新并测试了我使用字符串替换的答案,在这种特殊情况下它比使用basename更快(无需为此调用basename)。再次感谢您的建设性评论。

–Simply_Me
14年8月13日在1:30

#5 楼

如果目录位于同一文件系统上,则可以使用--linkcp选项合并两个目录的方法更快,更节省空间,这在相关文章的多个不同答案中都有介绍:(本文标题不t完全符合用户的问题,答案将解决标题问题(合并),而不是解决用户的实际问题。)
使用mv合并文件夹?
--linkcp选项表示没有文件数据复制。这样的一个示例,其中/images2中的所有内容替换/images中的所有较旧项为:合并会尝试将目录合并到具有相同名称的现有文件或符号链接中,即不会将名为cp --force --archive --update --link /images2/. /images的目录合并至具有相同名称/images的现有文件或符号链接中,如果出现此类错误,则可以手动删除文件或符号链接,然后重新运行命令。
关于rm -rf /images2的好处是,没有数据被移动来合并目录。