复制第一列匹配时的第二列文件。

huangapple go评论59阅读模式
英文:

Copy the file in second column when the first column match

问题

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

main_file

这里是行
另一行
Include 'file1'
include 'file2'
文件结束

期望的输出
文件1和文件2已复制到dir1目录

我的脚本

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

I would like to copy the files listed in the 2nd column of a text file to directory dir1, if the 1st column is "include" or "Include". my script just prints out all lines without copying the files.

main_file

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

desired output
file1 & file2 copied in the dir1 directory

my script

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

答案1

得分: 2

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

由于这里的目标是执行操作系统级文件复制,可能更直接的方法是在 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
# 没有输出 => 目录中没有任何内容

在运行任何一组代码(awkbash)之后:

$ ls -l dir1
-rw-rw----+ 1 用户名 用户组 30 6月 29 10:50  file1
-rw-rw----+ 1 用户名 用户组 90 6月 29 10:50  file2
-rw-rw----+ 1 用户名 用户组  0 6月 29 10:50 'file3 with spaces'

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

英文:

To perform an OS operation (eg, cp) from within awk you'll want to look at the system() function, eg:

awk -F&quot;&#39;&quot; &#39;tolower($1) ~ /^include / {system(&quot;cp \&quot;&quot; $2 &quot;\&quot; dir1&quot;)}&#39; main_file

Since the objective here is to perform an OS-level file copy it may be more straightforward to do this in bash ...

Adding a file with spaces in the name and creating the files/dir:

$ cat main_file
lines here
another line
Include &#39;file1&#39;
include &#39;file2&#39;
include &#39;file3 with spaces&#39;
endoffile

$ touch file1 file2 &#39;file3 with spaces&#39;
$ mkdir dir1

One idea:

while IFS=&quot;&#39;&quot; read -r _ fname _
do
    cp &quot;$fname&quot; dir1
done &lt; &lt;(grep -i &#39;^include &#39; main_file)

Before running either set of code (awk, bash):

$ ls -l dir1
                     # no output =&gt; nothing in directory

After running either set of code (awk, bash):

$ 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 &#39;file3 with spaces&#39;

NOTE: both solutions (awk, bash) assume the file names are always wrapped in single quotes and the file names do not include any single quotes

答案2

得分: 1

I want to explain what your code

is actually doing:

tolower($1)=="include" does a case-insensitive comparison, checking if the 1st column is "include" in any case. It includes variations like "Include," "INCLUDE," and so on.

{cp $2 dir1} does string concatenation. If cp and dir1 are undefined, GNU AWK assumes they are empty strings. Since you didn't specify what to do with this concatenation, nothing is printed.

As far as I know, GNU AWK doesn't have a built-in function for copying files. However, you can use GNU AWK to prepare instructions for bash like this:

Please note that this solution may have limitations and could break if dir1 doesn't exist or if there are single quotes within the file names. Consider using a programming language with better file handling features if possible.

英文:

I want to explain what your code

awk &#39;tolower($1)==&quot;include&quot;{cp $2 dir1}&#39; main_file

is actually doing

tolower($1)==&quot;include&quot; does case-insensitive comparison, this bit more sensitive that 1st column is "include" or "Include". (which would be expressed as $1==&quot;include&quot;||$1==&quot;Include&quot;) as it also holds for INCLUDE, InClUdE and so on, but if these do not appear or should be treated same way will be ok.

{cp $2 dir1} does string concatenation, as cp and dir1 were not defined, GNU AWK assumes that they are empty strings. As you did not instruct GNU AWK what to do with effect of concatenation nothing is printed (at least in GNU Awk 5.1.0, which I used for testing).

As far as I know GNU AWK has not function for copying files, however you might use GNU AWK to prepare set of instructions for bash following way

awk &#39;tolower($1)==&quot;include&quot;{print &quot;cp &quot; $2 &quot; dir1&quot;}&#39; main_file | bash

Keep in mind that such solution is prone to breakage, as it did not care about dir1 existence and might malfunction if there is &#39; inside name of file, so if possible consider using language which sports features for dealing with copying files.

答案3

得分: 1

$ cat main_file
lines here
another line
包括 'file1'
包括 'file2'
包括 'file3 with spaces'
endoffile

$ grep -i "^include " main_file | xargs -n2 sh -c '[ -f "$1" ] && cp "$1" dir1/'

$ ls dir1
file1 file2 'file3 with spaces'

英文:
$ cat main_file 
lines here
another line
Include &#39;file1&#39;
include &#39;file2&#39;
include &#39;file3 with spaces&#39;
endoffile

$ grep -i &quot;^include &quot; main_file | xargs -n2 sh -c &#39;[ -f &quot;$1&quot; ] &amp;&amp; cp &quot;$1&quot; dir1/&#39;

$ ls dir1
file1   file2  &#39;file3 with spaces&#39;

huangapple
  • 本文由 发表于 2023年6月29日 23:38:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76582602.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定