我有一个包含两列和超过 3,00,000 行的文本文件。格式如下
Filename1.txt Num1
Filename2.txt Num2
Filename3.txt Num3
我想将对应Numx
大于 50 且小于 200 的所有文件名复制到另一个文件中。
将这些文件名复制到另一个文件后,我想将所有这些文件复制到另一个文件夹中。
我怎么做?
答案1
如果您愿意,可以同时进行比较和复制awk
:
awk '$2>50 && $2<200 {system("cp -- "$1" /path/to/destination/")}' file.txt
假设您要将文件复制到destination
目录,请更改此值以满足您的需要。
$2>50 && $2<200
进行所需的比较如果匹配,则
cp
执行操作 ({system("cp -- "$1" /path/to/destination/")}
),由system()
函数完成awk
答案2
让我们考虑这个测试文件:
$ cat file
Filename1.txt 49
Filename2.txt 72
Filename3.txt 189
Filename4.txt 203
仅选择第二列大于或等于 50 且小于或等于 200 的文件:
$ awk '$2>=50 && $2<=200 { print $1}' file
Filename2.txt
Filename3.txt
要将这些文件名放入某个路径的新文件中:
awk '$2>=50 && $2<=200 { print $1}' file >/path/to/newfile
复制选定的文件
假设数字是整数,请尝试:
while read fname num; do [ "$num" -ge 50 ] && [ "$num" -le 200 ] && cp -- "$fname" /some/path/ ; done <file
或者,对于那些喜欢将代码分散在多行中的人:
while read fname num
do
[ "$num" -ge 50 ] && [ "$num" -le 200 ] && cp -- "$fname" /some/path/
done <file
答案3
问题已标记sed和grep,所以我假设有人对使用正则表达式的答案感兴趣。另外,问题表明输入数据文件很大,因此我认为性能是一个考虑因素。
我还假设,鉴于输入文件每行包含一个文件名,因此不会有包含换行符的(病态)文件名。
其他答案有效地cp
为每个文件生成一个进程。这会导致不必要的性能降低。相反,我们可以使用命令行xargs
来调用cp
尽可能多的文件名。
sed -rn 's/ (5[1-9]|[6-9].|1..)$//p' input.txt | tr '\n' '\0' | xargs -0 cp -t /destdir
使用sed
正则表达式来匹配闭合数值区间(50, 200)
。使用正则表达式来解决数值不等式并不总是最优雅的事情,但在这种情况下,所需的表达式相当简单。
我们假设文件名不包含换行符,但它们可能包含其他无用的字符,例如空格。 xargs
如果给定分隔数据,将正确处理此问题\0
,因此我们使用tr
将所有换行符转换为空字符。
上面假设sed
和是 GNU 版本xargs
。如果您有 BSD 版本(例如 OSX),则命令略有不同:
sed -En 's/ (5[1-9]|[6-9].|1..)$//p' input.txt | tr '\n' '\0' | xargs -0 -J {} cp {} /destdir
这些命令将生成sed
、tr
和的一份副本xargs
。将会有多个 的生成cp
,但每个生成都会复制多个文件 -xargs
将尝试填充每个cp
命令行以实现高效利用。当输入数据很大时,这应该比其他答案提供显着的性能改进。