Bash Shell awk/xargs 魔法

5

我正在尝试学习一些awk技巧。我的CSV文件每行都是部分文件名和文件路径的格式。我的目标是根据部分名称找到这些文件并将它们移动到相应的新路径。我想要结合find、awk和mv的力量来实现这个目标,但我在实施过程中遇到了困难。我想使用awk来从csv文件中分离术语,以便我可以执行以下操作:
find . -name '*$1*' -print | xargs mv {} $2{}
其中$1和$2是来自csv文件的拆分术语。有人有什么想法吗?-安宁

4个回答

6
我建议这样做:
$ cat korv
foo.txt,/hello/
bar.jpg,/mullo/
$ awk -F, '{print $1 " " $2}' korv
foo.txt /hello/
bar.jpg /mullo/

-F设置分隔符,因此上面的代码将使用“,”进行拆分。接下来,在文件名中添加*:

$ awk -F, '{print "*"$1"*" " " $2}' korv
*foo.txt* /hello/
*bar.jpg* /mullo/
**

这显示我有一个空行。我们不想匹配这个,因此我们添加了以下规则:
$ awk -F, '/[a-z]/{print "*"$1"*" " " $2}' korv
*foo.txt* /hello/
*bar.jpg* /mullo/

看起来不错,将所有内容封装到 mv 中使用子shell:

$ mv $(awk -F, '/[a-z]/{print "*"$1"*" " " $2}' korv)
$

完成。


不,xargs -i 当然也支持 {},但它一次只接受一个参数。 - tripleee
1
你忘记了在 xargs -i 中加上 -i - tripleee
此外,使用反引号运行它将会复制所有文件到最终目标目录。 - tripleee
只是为了明确 tripleee 的建议(我假设你的意思是大写字母 -I):echo foo | xargs -n 1 -I {} echo mv {} {}.txt => mv foo foo.txt - Joshua Goldberg
2
你可以多次使用{},例如find . -name file -exec mv {} {}.txt \;是有效的。 - Milo Wielondek
显示剩余2条评论

1

你不需要用awk来完成这个任务。在这里,awk并没有比shell更好的地方。

#!/bin/sh
IFS=,
while read file target; do
  find . -name "$file" -print0 | xargs -ir0 mv {} "$target"
done <path_to_csv_file

如果文件名中有特殊字符,您可能需要调整read


0

使用awk的system命令怎么样:

awk '{ system("find . -name " $1 " -print | xargs -I {} mv {} " $2 "{}"); }'

CSV文件中的示例参数:test.txt ./subdirectory/


感谢您的帮助。我之前不知道这个命令。那么完整的调用是这样的吗: awk '{ system("find . -name " $1 " -print | xargs -I {} mv {} " $2 "{}"); }' path_to_csv_file - adbo
最后一个“{}”是用来干什么的?至少对我而言,如果你将其删除,它会更有效。 - tripleee
@adbo:使用-F选项运行它,以便读取csv文件。Bos的解决方案更好,假设您只想复制当前目录中的文件(在这种情况下,find命令变得完全不必要)。 - aleph_null
@tripleee:虽然它仍然可以与最后一个{}一起使用,但你说得对,这并不是必要的。mv file.txt ./subdir/file.txt与mv file.txt ./subdir/相同。回想起来,我会把它拿掉。 - aleph_null

0
find . -name "*err" -size "+10c" | awk -F.err '{print $1".job"}' | xargs -I {} qsub {}

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