shell 当第一列匹配时复制第二列中的文件

u4vypkhs  于 2023-06-30  发布在  Shell
关注(0)|答案(2)|浏览(160)

如果第一列是“include”或“Include”,我想将文本文件的第二列中列出的文件复制到目录dir1。我的脚本只是打印出所有行,而不复制文件。

主文件

lines here
another line
Include 'file1'
include 'file2'
endoffile

所需输出复制到dir1目录中的file1和file2
我的剧本

awk 'tolower($1)=="include"{cp $2 dir1}' main_file
whlutmcx

whlutmcx1#

要在awk中执行OS操作(例如,cp),您需要查看system()函数,例如:

awk -F"'" 'tolower($1) ~ /^include / {system("cp \"" $2 "\" dir1")}' main_file

由于这里的目标是执行操作系统级别的文件复制,因此在bash中执行此操作可能更简单...
添加一个名称中带有空格的文件,并创建文件/目录:

$ cat main_file
lines here
another line
Include 'file1'
include 'file2'
include 'file3 with spaces'
endoffile

$ touch file1 file2 'file3 with spaces'
$ mkdir dir1

一个想法:

while IFS="'" read -r _ fname _
do
    cp "$fname" dir1
done < <(grep -i '^include ' main_file)

在运行任意一组代码(awkbash)之前:

$ ls -l dir1
                     # no output => nothing in directory

运行任意一组代码(awkbash)后:

$ ls -l dir1
-rw-rw----+ 1 username None 30 Jun 29 10:50  file1
-rw-rw----+ 1 username None 90 Jun 29 10:50  file2
-rw-rw----+ 1 username None  0 Jun 29 10:50 'file3 with spaces'

**注意:**两种解决方案(awkbash)都假定文件名始终用单引号括起来 *,并且 * 文件名不包含任何单引号

neekobn8

neekobn82#

我想解释一下你的代码

awk 'tolower($1)=="include"{cp $2 dir1}' main_file

实际上是在做
tolower($1)=="include"进行不区分大小写的比较,这一点比 * 第一列是“include”或“Include”.*(将表示为$1=="include"||$1=="Include")更敏感,因为它也适用于INCLUDE,InClUdE等,但如果这些没有出现或应该以相同的方式处理也是可以的。
{cp $2 dir1}进行字符串连接,因为cpdir1没有定义,GNU AWK假设它们是空字符串。由于您没有指示GNU AWK如何处理连接的效果,因此没有打印任何内容(至少在我用于测试的GNU Awk 5.1.0中是这样)。
据我所知,GNU AWK没有复制文件的功能,但是你可以使用GNU AWK来准备bash的指令集,如下所示

awk 'tolower($1)=="include"{print "cp " $2 " dir1"}' main_file | bash

请记住,这样的解决方案很容易被破坏,因为它不关心dir1的存在,如果文件名中有',可能会发生故障,所以如果可能的话,请考虑使用具有处理复制文件功能的语言。

相关问题