find命令后如何集成mv命令?

hua*_*n68 90 find files mv

我正在AAA使用以下命令搜索名称包含在其路径中的文件:

find path_A -name "*AAA*"
Run Code Online (Sandbox Code Playgroud)

鉴于上述命令显示的输出,我想将这些文件移动到另一个路径,例如path_B. 我可以通过在 find 命令之后立即移动这些文件来优化命令,而不是一个一个地移动这些文件吗?

cuo*_*glm 133

使用 GNU mv

find path_A -name '*AAA*' -exec mv -t path_B {} +
Run Code Online (Sandbox Code Playgroud)

这将使用 find 的-exec选项,该选项{}依次替换每个查找结果并运行您提供的命令。如中所述man find

   -exec command ;
          Execute  command;  true  if 0 status is returned.  All following
          arguments to find are taken to be arguments to the command until
          an  argument  consisting of `;' is encountered.  
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们使用的是 的+版本,-exec以便我们运行尽可能少的mv操作:

   -exec command {} +
          This  variant  of the -exec action runs the specified command on
          the selected files, but the command line is built  by  appending
          each  selected file name at the end; the total number of invoca?
          tions of the command will  be  much  less  than  the  number  of
          matched  files.   The command line is built in much the same way
          that xargs builds its command lines.  Only one instance of  `{}'
          is  allowed  within the command.  The command is executed in the
          starting directory.
Run Code Online (Sandbox Code Playgroud)

  • @JeremyDavis 使用 `-exec ... {} +` 时,`{}` 必须是 `+` 之前的最后一个。这就是他使用 `mv -t destdir {} +` 而不是 `mv {} destdir +` 的原因。一个感冒使用了 `-exec mv {} destdir ';'` 代替,但是那样会为每个文件执行一次 `mv`。 (10认同)
  • 不要忘记“\;” 在 exec 结束时! (3认同)
  • @Charles Roth:完成工作的是`+`,你可以阅读我上面的引述或`man find` (2认同)

Ram*_*esh 29

您也可以执行以下操作。

find path_A -name "*AAA*" -print0 | xargs -0 -I {} mv {} path_B
Run Code Online (Sandbox Code Playgroud)

在哪里,

  1. -0如果有空格或字符(包括换行符),许多命令将不起作用。此选项处理带有空格的文件名。
  2. -I用从标准输入读取的名称替换初始参数中出现的 replace-str。此外,未加引号的空格不会终止输入项;相反,分隔符是换行符。

测试

我创建了两个目录作为sourcedirdestdir。现在,我在sourcediras 中创建了一堆文件file1.bakfile2.bak并且file3 with spaces.bak

现在,我执行了命令,

find . -name "*.bak" -print0 | xargs -0 -I {} mv {} /destdir/
Run Code Online (Sandbox Code Playgroud)

现在,里面的destdir,当我这样做ls,我可以看到文件已经从移动sourcedirdestdir

参考

http://www.cyberciti.biz/faq/linux-unix-bsd-xargs-construct-argument-lists-utility/

  • 在 macOS 上运行良好(其中 `-t` 参数在 `mv` 上不可用 (3认同)

小智 28

为了让遇到此问题的 OS X 用户受益,OS X 中的语法略有不同。假设您不想在以下子目录中递归搜索path_A

find path_A -maxdepth 1 -name "*AAA*" -exec mv {} path_B \;
Run Code Online (Sandbox Code Playgroud)

如果要递归搜索所有文件path_A

find path_A -name "*AAA*" -exec mv {} path_B \;
Run Code Online (Sandbox Code Playgroud)

  • 这不是 OS X 特定的语法,它与我使用过的任何“find”语法相同。优点: `-maxdepth` (特别是如果 path_B 是一个子目录 - 避免 `mv` 尝试移动已经存在的文件!)并使用 \; (因此 {} 不必是最后一个参数,可以使用正常的 `mv` 语法) (3认同)

ter*_*don 7

-exec是最好的方法。如果出于某种原因,这不是一个选项,您还可以在循环中读取结果:

find path_A -name "*AAA*" -print0 | 
    while IFS= read -r -d $'\0' file; do mv "$file" path_B; done
Run Code Online (Sandbox Code Playgroud)

这是一种安全的方式,它可以处理包含空格、换行符或其他奇怪字符的文件名。这更简单的方法,但一个失败,除非你的文件名只包含简单的字母数字字符,是

mv $(find path_A -name "*AAA*") path_B
Run Code Online (Sandbox Code Playgroud)

但是使用while循环。


Wil*_*ard 6

只使用的POSIX功能find(和mv):

find path_A -name '*AAA*' -exec sh -c 'mv "$@" path_B' find-sh {} +
Run Code Online (Sandbox Code Playgroud)

进一步阅读: