使用特定的名称模式将数百万个文件移动到另一个目录


10

我在Linux机器上有数百万个具有以下术语的文件:

1559704165_a1ac6f55fef555ee.jpg

前10位数字是时间戳,后跟数字_是特定ID。我想将所有与特定文件名ID匹配的文件移动到另一个文件夹。

我在带有文件的目录上尝试过

find . -maxdepth 1 -type f | ??????????_a1ac*.jpg |xargs mv -t "/home/ubuntu/ntest"

但是我收到一条错误消息,指出:

bash 1559704165_a1ac6f55fef555ee.jpg: command not found

当我尝试mv ??????????_a1ac*.jpg 时,出现参数列表过长的错误。我至少有15种不同的文件名模式。我该如何移动它们。


1
bash可以说明一切:它尝试执行该文件名,因为它是管道第二阶段中的第一个文件名(您的第二阶段管道是 | ??????????_a1ac*.jpg::bash将其扩展为几个文件名,第一个是1559704165_a1ac6f55fef555ee.jpg,因为这样您最终,在第二个管道阶段尝试执行: 1559704165_a1ac6f55fef555ee.jpg next_matching_filename 3rd_matching_filename ... nth_matching_filename。我猜您是试着改为过滤到该文件名(请参见下面的答案)
Olivier Dulac

Answers:


15

您应该使用:

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' \
-exec mv -t destination "{}" +

因此,maxdepth 1意味着您要在当前目录中搜索没有子目录。

type f 表示仅查找文件。

name '??????????_a1ac*.jpg' 是与您要搜索的文件匹配的模式。

mv -t destination "{}" +表示将匹配的文件移到目标位置。这里+将新的匹配文件添加到上一个文件中,例如:

mv -t dest a b c d

这里abcd是不同的文件。


感谢您简要回答此人的问题。与其简单地倾销解决方案,不如说您可以解释如何/什么/为什么。而不是一次对一个人有用,它可以一直对所有人有用。在过去的40至50年中,无数次询问和回答了相同的问题。问题是,从来没有很好地解释过。教一个人钓鱼。。其间:gnu.org/software/findutils/manual/html_node/find_html/…而且通常情况下,Wikipedia比官方文档更有用:en.wikipedia.org/wiki/Find_( Unix)
声音

查看最新答案。
Prvt_Yadav

请注意,这-t是GNU扩展,因此在其他类型的UNIX派生类中可能不可用。
凯文

当您说“双引号可以防止单词分裂”。我假设您是指"{}",在这种情况下,我想指出的是该{}内容不会被shell扩展,也不需要被引用。外壳传递{}给find,find看到{}并用路径名替换它。Find exec不使用Shell解析器,也不进行任何单词拆分。引用它没有任何害处,只是给出的理由有些不准确。
jw013 '19

@ jw013谢谢。
Prvt_Yadav

11

你的命令

find . -maxdepth 1 -type f | ??????????_a1ac*.jpg |xargs mv -t "/home/ubuntu/ntest"

将所有文件的列表传送到所有文件!

find . -maxdepth 1 -type f -name `*_a1ac*.jpg` -print0 |\
xargs  -0 -r mv -t "/home/ubuntu/ntest"

会成功的


1
非常感谢...您的解决方案也起作用...感谢您让我知道我哪里出了错

8

你很亲密 您应该使用-name选项find。并记住引用该模式。

所以

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' |xargs mv -t "/home/ubuntu/ntest"

非常感谢...您的解决方案也起作用。...感谢您让我知道我已经接近解决方案....它是像我这样的新手的动力

1
您应该-print0在查找中添加a 作为最后一个参数(而不是默认值:-print),并-0在xargs中添加a 作为第一个选项(即:)xargs -0 mv -t "/home/ubuntu/ntest"。这样,就可以处理所有奇怪的文件名(其中包含空格,“ newline”等)。find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' -print0 |xargs -0 mv -t "/home/ubuntu/ntest" (尽管仅适用于类似GNU的查找)
Olivier Dulac

2

不如find解决方案“好” ,但是另一个有效的解决方案是使mv命令更精细。

这样做可以进行4096次移动,而每次mv操作移动的文件数量较少。

FILEPAT=a1ac
for i in $(seq $((0x000)) $((0xfff))); 
do 
   H=$(printf '%x\n' $i)
   mv 1559704165_${FILEPAT}${H}*.jpg /home/ubuntu/ntest
done

对于没有find(出于任何原因)的人来说,这是一个聪明的技巧。
森林

-1

如果您想在同一主机系统上移动文件,我想您正在使用mv,这rsync可能是一个更快的选择:

rsync -av --inplace -W /source/??????????_a1ac*.jpg /home/ubuntu/ntest/

--inplace-W设置为加快该过程。

如果这产生另一个参数列表过长的错误,则可以将列表提供给rsync

以查找为清单,例如

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txt

并给 rsync

rsync -av --inplace -W --files-from=/tmp/my_image_list.txt /path/to/files /home/ubuntu/ntest/

此处的来源是/path/to/files,因为rsync会将您提供的列表视为相对于来源的列表。


关键是:如果文件不在同一文件系统上,则rsync比更快mv


OP可能会碰到相同的“参数列表太长”错误
脾气暴躁,

@Grump,为避免这种情况,OP可以将要复制的文件列表写入文件,即find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txt,然后将其传递给rsync --files-from=/tmp/my_image_list.txt。关键rsync是更快。除非文件位于相同的文件系统上,否则OP不会指出。
罗伯特·里德尔

@RobertRiedl:您应该编辑答案并添加此信息。评论可以是无常的。
NickD

@NickD,我更新了答案。
罗伯特·里德尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.