Bash脚本:移动指定名称的前N个文件

3

我想要移动当前目录中特定扩展名的100个文件到上级目录,但我的尝试没有成功。

for file in $(ls -U | grep *.txt | tail -100)
do
    mv $file ../
done

你能指导我正确的方法吗?


grep *.txt is not correct, since the shell expands the wildcard. Use ls *.txt - Barmar
1
@Barmar,解析ls的输出是一个臭名昭著的陷阱。用户应该依赖于find - Enlico
@Enrico 我知道,尽管任何管道到 tail -100 的解决方案都会遇到类似的问题。 - Barmar
@Barmar,当然,但我不确定将其导入tail是唯一的方法。也许是,我们来看看。此外,OP没有解释“100个文件”的含义。按字母顺序排序的前100个?最大的100个文件?谁知道... - Enlico
1
“-U” 禁用排序,因此它似乎意味着以目录中存储的任何顺序显示最后的 100 个文件。 - Barmar
显示剩余2条评论
3个回答

4

由于你没有引用*.txt,Shell将其扩展为所有以.txt结尾的文件名。所以你的命令类似于:

ls -U | grep file1.txt file2.txt file3.txt ... | tail -100

grep 带有文件名参数,因此它会忽略标准输入。它输出所有与 file1.txt 匹配的行在其余的文件中。可能没有匹配,所以没有东西被传送到 tail -100。即使有匹配,输出也将是文件中的行而不是文件名,因此对于 mv 命令没有用。

您可以直接循环遍历文件名,并使用计数器变量在 100 个文件后停止。

counter=0
for file in *.txt
do
    if (( counter >= 100 ))
    then break
    fi

    mv "$file" ../
    ((counter++))
done

这样可以避免解析ls的输出所带来的问题。

“bash” 通过按字母数字顺序对文件名模式进行排序来扩展它。OP 想要按目录顺序获取前 100 个。老实说,我不知道我们如何在 bash 中实现这一点(而不诉诸于“ls”)。 - user1934428
1
说实话,我想不出他为什么真的想按目录顺序做这件事,因为那与任何有意义的事情都没有关系。按修改时间顺序做更有意义。 - Barmar
但如果不是这样,字典顺序可能和其他任何东西一样好。 - Barmar
我也不确定,但是观察到他在命令中明确使用了“-U”标志,我认为他想要按目录顺序排列。 - user1934428
或许他并不在意顺序,而是试图通过不排序来提高性能。 - Barmar
显示剩余3条评论

0

这个可以完成任务:

ls -U *.txt | tail -100 | while read filename; do mv "$filename" ../; done

while read filename 保留文件名中的空格。


你忘记了 ls 命令的 -U 参数。此外,我不太清楚这个解决方案在哪些方面比 OP 提出的更好。 - user1934428
@user1934428 在原帖中误用了 grep - Barmar

0

在文本文件目录中运行此命令:

#!/bin/bash

for txt_file in ./*.txt; do
        ((c++==100)) && break
        mv "$txt_file" ../
done

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接