将所有 PDF 文件移动到事先不存在的单独目录中

将所有 PDF 文件移动到事先不存在的单独目录中

我正在编写一个简单的方法来批量移动文件,并尝试了两种方法:

#(1)
find . -name '*.pdf' | xargs -I{} mkdir pdfs; mv {} pdfs 

#(2)
find . -name '*.pdf' -exec mv {} pdfs \+

第一种方法“有时”出人意料地有效,但是,在多次删除包含 pdf 的文件夹并将 pdf 返回到父目录后,它突然停止工作。

它会产生以下错误:

mv: rename {} to pdfs: No such file or directory
xargs: unterminated quote

而第二种方法会出现以下错误:

find: -exec: no terminating ";" or "+"

更新:

我让它与:

find . -name '*.pdf' -exec mv "{}" pdfs \;

但是,如果我想在一行中创建目录并移动文件,这将不起作用,例如:

find . -name '*.csv' -exec mkdir -p csvs && mv "{}" csvs \;

查找:-exec:没有终止“;”或“+”

如何实现目录的创建和移动?

答案1

假设您的情况确实如此简单(文件以 .pdf 结尾),一个简单的

mv -- **/*.pdf pdfs/

会做。

对于 zsh,**默认情况下启用递归 glob,对于 bash,您必须首先使用 启用它shopt -s globstar

我怀疑您的 find 调用实际上可能稍微复杂一些。但特别是如果您使用 zsh,您的 shell 的扩展通配符功能非常强大,并且通常可以让您免去记住每次都有效的正确 magic find 参数的麻烦;)

答案2

像这样的东西应该有效:

$ touch foo.pdf white\ space.pdf
$ ls
 foo.pdf  'white space.pdf'
$ mkdir pdfs && \
    find . -path ./pdfs -prune \
    -o -name '*.pdf' -exec mv {} pdfs/ \;
$ tree
.
└── pdfs
    ├── foo.pdf
    └── white space.pdf
  1. 这将创建目录pdfs,并且仅在成功创建后才继续。
  2. 这会查找以 结尾的所有文件,.pdf同时确保它与已移动到pdfs目录的文件不匹配(该-path pdfs -prune部分会跳过此目录中的文件)。
  3. mv每场比赛执行一次。使用mv -t pdfs/ {} \+(GNU 扩展)来提高性能。

答案3

不带引号的命令将命令与命令;分开,因此不可能起作用。mvfind

迄今为止最简单的解决方案是在运行之前创建目标目录find。如果你不想保留空目录,可以rmdir稍后再保留;如果目录包含任何文件,这将失败。

如果您有 GNU mv,它有一个-t选项可以让您方便地在要移动的文件之前命名目标目录,以便您可以说

mkdir pdfs
find . -name '*.pdf' -exec mv -t pdfs {} +
rmdir pdfs || true

如果你没有mv -t,请尝试类似的方法

find . -name '*.pdf' -exec sh -c 'mv "$@" "$0"' pdfs {} +

我们无耻地使用“zeroth”参数来sh -c将目标目录名称与参数列表分开传递"$@"。 (按照惯例,这个“第 0 个”参数将包含 shell 的名称,但由于这对这里的任何内容都没有用,并且字符串无论如何都必须包含某些内容,因此我们可以进行一些修改,这样我们就不必处​​理参数列表.)

find ... -exec mv {} pdfs \;

可以工作,但效率有些低,因为它mv为每个找到的文件运行一个单独的命令。+终止符表示-exec为尽可能多的文件运行单个子进程(类似于xargs),但要求{}令牌位于最后。

答案4

一种方法是,使用珀尔的rename:

touch foo.pdf white\ space.pdf $'new\nline.pdf'
find . -name '*pdf' -print0 | rename -n -0 's|[^/]+\.pdf$|./pdfs/$&|ms'

-n当尝试令人满意时放弃。

相关内容