我有许多文件,它们在目录中按文件名排序。我希望将最后的 N 个(比如 N=4)文件复制到我的主目录中。我该怎么做呢?
cp ./<the final 4 files> ~/
答案1
这可以使用 bash/ksh93/zsh 数组轻松完成:
a=(*)
cp -- "${a[@]: -4}" ~/
这适用于所有非隐藏文件名,即使它们包含空格、制表符、换行符或其他困难字符(假设当前目录中至少有 4 个带有 的非隐藏文件bash
)。
怎么运行的
a=(*)
a
这将创建一个包含所有文件名的数组。 bash 返回的文件名按字母顺序排序。 (我认为这就是你的意思“按文件名排序。”)${a[@]: -4}
这将返回数组的最后四个元素
a
(前提是该数组至少包含 4 个带有 的元素bash
)。cp -- "${a[@]: -4}" ~/
这会将最后四个文件名复制到您的主目录。
同时复制和重命名
这将仅将最后四个文件复制到主目录,同时将字符串添加a_
到复制文件的名称前面:
a=(*)
for fname in "${a[@]: -4}"; do cp -- "$fname" ~/a_"$fname"; done
从不同的目录复制并重命名
如果我们使用a=(./some_dir/*)
而不是a=(*)
,那么我们就会遇到目录附加到文件名的问题。一种解决方案是:
a=(./some_dir/*)
for f in "${a[@]: -4}"; do cp "$f" ~/a_"${f##*/}"; done
另一个解决方案是使用子 shell 并cd
访问子 shell 中的目录:
(cd ./some_dir && a=(*) && for f in "${a[@]: -4}"; do cp -- "$f" ~/a_"$f"; done)
当子 shell 完成时,shell 将我们返回到原始目录。
确保顺序一致
该问题询问“按文件名排序”的文件。奥利维尔·杜拉克 (Olivier Dulac) 在评论中指出,这一顺序会因地区而异。如果独立于机器设置的固定结果很重要,那么最好在a
定义数组时显式指定区域设置。例如:
LC_ALL=C a=(*)
您可以通过运行该命令来了解您当前所在的区域设置locale
。
答案2
如果您正在使用,zsh
您可以将()
所谓的列表括在括号中全局限定符选择所需的文件。在你的情况下,那就是
cp *(On[1,4]) ~/
这里On
按相反的字母顺序对文件名进行排序,并且[1,4]
只取其中的前 4 个。
您可以通过仅选择带有 的纯文件(不包括目录、管道等)来使其更加健壮.
,并且还可以附加--
到cp
命令以正确处理名称以-
正确开头的文件,因此:
cp -- *(.On[1,4]) ~
D
如果您还想考虑隐藏文件(点文件),请添加限定符:
cp -- *(D.On[1,4]) ~
答案3
这是使用极其简单的 bash 命令的解决方案。
find . -maxdepth 1 -type f | sort | tail -n 4 | while read -r file; do cp "$file" ~/; done
解释:
find . -maxdepth 1 -type f
查找当前目录中的所有文件。
sort
按字母顺序排序。
tail -n 4
只显示最后 4 行。
while read -r file; do cp "$file" ~/; done
循环执行复制命令的每一行。
答案4
如果只有文件并且它们的名称不包含空格或换行符(并且您没有修改过$IFS
)或全局字符(或一些具有某些实现的不可打印字符ls
),并且不以 开头.
,那么您可以这样做:
cp -- $(ls | tail -n 4) ~/