我想将一个目录中的 1000 个文件移动到另一个目录。如果我在原来的目录中我可以做到,但是如果我尝试这个
mv $(ls /home/jeremy/source|tail -1000) /home/jeremy/dest
从其他地方,路径被剥离,所以我需要以某种方式附加路径。我发现 $ 很方便,并且想避免 xargs,因为它看起来很棘手。
答案1
如果你的命令在命令行不会变得太长的情况下可以工作,那么你可以xargs
这样使用(棘手的):
ls /home/jeremy/source | tail -1000 | xargs mv -t /home/jeremy/dest
这假设文件名(或路径)中没有换行符和其他特殊字符,否则 tail 将无法正常工作,并且 xargs 将获得分割文件名(因为它在行上工作,除非您指定xargs -0
)。
参数-t
允许mv
您在需要复制到目标的文件参数之前指定目标目录。
答案2
使用最新的 [1] 版本的 GNUfindutils
和coreutils
:
find /home/jeremy/source -print0 |
tail -z -n 1000 |
xargs -0 -r mv -t /home/jeremy/dest/
-print0
、-z
和选项-0
告诉所有三个工具使用 NUL 字符作为文件名/记录分隔符。这使得可以安全地使用包含任何字符的文件名的管道。
如果您的tail
(或head
) 版本不支持该-z
选项,您可以使用换行符作为文件名分隔符(这对于除包含换行符之外的任何文件名都是安全的):
find /home/jeremy/source |
tail -n 1000 |
xargs -r -d '\n' mv -t /home/jeremy/dest/
顺便说一句,xargs
一点也不棘手。这是一个相当简单的命令,它从 stdin 获取数据并使用它来运行程序(来自 stdin 的数据用作该程序命令行上的参数)。这是一个非常有用的工具,非常值得花少量的时间来学习。
更重要的是,与$(ls ...)
和相似的不同,使用xargs
避免了大多数(如果您使用 NUL 作为分隔符)问题,包括空格、shell 通配符(通配符等)和其他烦人的字符(这些字符在文件名中是完全合法的字符,因此编写良好的脚本会小心不要被它们破坏)。
[1] 我不知道什么时候head
有tail
选项-z
,但在过去的几年里,许多 GNU 工具(包括sort
)已经获得了使用 NUL 作为输入记录分隔符的能力。在此之前,只有少数工具,例如find
和xargs
。
这非常有用,因为您现在可以使用这些-z
或-Z
或-0
等选项来构建长而复杂的管道,而不必丢失有用的 NUL 分隔。