我想从一个目录树中移动大于“300Mb”的文件,其中每个文件都位于子文件夹中
示例:我有一个目录结构:
dirA/
dirA/file1
dirA/x/
dirA/x/file2
dirA/y/
dirA/y/file3
这是预期的结果,目录树的“移动”,其中每个文件都移动到子文件夹:
dirB/ # normal directory
dirB/file1 # moved from dirA/file1
dirB/x/ # normal directory
dirB/x/file2 # moved from dirA/x/file2
dirB/y/ # normal directory
dirB/y/file3 # moved from dirA/y/file3
但find /path/ -type f -size +300m
然后呢?不幸的是,有些文件包含您可以在键盘上找到的各种字符。
我一直在看这个线有人在谈论cpio
但我不知道那个程序......
PS:安装了 GNU Parallel 是否可以加快速度?
答案1
最简单的方法是桀骜。您可以使用全局限定符根据文件类型和大小等标准来匹配文件。这通配符模式 **/
匹配任何级别的子目录。这历史修改器 h
和t
是提取目录和文件名的基本部分的简单方法。需要时调用mkdir -p
创建目录。
cd dirA
for x in **/*(.Lm+300); do
mkdir -p ../dirB/$x:h &&
mv -- $x ../dirB/$x
done
便携式方式是使用find
.用于-exec
为每个文件调用 shell 片段。
cd dirA
find . -type f -size +300000k -exec sh -c 'for x do
mkdir -p "../dirB/${x%/*}"
mv "$x" "../dirB/$x"
done' sh {} +
并行化对于输入/输出很少有用:它可以让您利用多个 CPU,但 CPU 很少成为 I/O 的瓶颈。
答案2
Perlrename
是显而易见的选择。它可以安装为ren
、rename
或pren
:
find dirA -type f -size +300M | ren 's:^dirA/:dirB/:'
但是,如果文件移动到不同的安装点,它就不起作用,如果目录不存在,它就会失败。
GNU Parallel 会更慢:
cd dirA
find . -type f -size +300M | parallel mkdir -p ../dirB/{//}
find . -type f -size +300M | parallel mv {} ../dirB/{}
但即使它需要执行复制然后删除例程以将文件转移到不同的文件系统上,它也会起作用。
答案3
简而言之:
find dirA -type f -size +300m -printf "mv %p dirB/%P\n" | sh
但是,在开始之前,dirB 中的所有子目录都必须存在。为此,我建议您执行以下两个步骤:
cd dirA
find . -type f -size +300m -printf "mkdir -p ../dirB/%h\nmv %p ../dirB/%P\n" | sh
关于cpio(实际上是解决子目录问题):
(cd dirA; find . -type f -size +300m) | cpio -p -md dirB
(关于您提到的同一线程中的 cp(1) ,这对您不利,因为它会复制 全部 文件 和 在 dirB 下构建名为 dirA 的子目录。旗帜-T可以解决这个问题)
答案4
这应该可以覆盖它。
find /path -type f -size +300m | while read A ; do DEST=${A/dirA/dirB} ; echo mkdir -p $(dirname $DEST) 2>/dev/null; echo mv $A $DEST ; done
首先按原样运行它,进行健全性检查,如果对建议的命令感到满意,则在不包含echo
元素的情况下重新运行它。
在您的文件结构示例中,将生成以下命令
mkdir -p ./dirB
mv ./dirA/file1 ./dirB/file1
mkdir -p ./dirB/x
mv ./dirA/x/file2 ./dirB/x/file2
mkdir -p ./dirB/y
mv ./dirA/y/file3 ./dirB/y/file3