使cat命令以递归方式循环遍历目录

时间:2016-08-24 05:46:56

标签: bash shell cat data-manipulation

我有一个大型数据文件目录,我正在操作以获得所需格式的数据文件。它们每个都过早开始和结束15行,这意味着我需要从一个文件中删除前15行并将它们粘贴到序列中上一个文件的末尾。

首先,我编写了以下代码,将相关数据分成简单的块:

#!/bin/bash

destination='media/user/directory/'
for file1 in `ls $destination*.ascii`
do
    echo $file1
    file2="${file1}.end"
    file3="${file1}.snip"
    sed -e '16,$d' $file1 > $file2
    sed -e '1,15d' $file1 > $file3
done

这很有效,所以下一步是世界上最简单的cat命令:

cat $file3 $file2 > outfile

然而,我需要做的是将file2拼接到之前的 file3。目的Look at this screenshot以便更好地理解。

了解这些文件是如何随时间变化的:

*_20090412T235945_20090413T235944_*    ### April 13
*_20090413T235945_20090414T235944_*    ### April 14

所以我需要从上面的4月14日示例中删除15行并将其粘贴到4月13日示例的末尾。

这不一定是原始代码的一部分,事实上如果不是原始代码可能是最好的。我只是希望有人能够帮助我实现这一目标。

提前致谢!如果有任何我不清楚的事情,需要进一步解释,请告诉我。

3 个答案:

答案 0 :(得分:4)

  

“我需要从一个文件中删除前15行并将它们粘贴到序列中前一个文件的末尾。”

如果我理解你想要什么,可以用一行代码完成:

awk 'NR==1 || FNR==16{close(f); f=FILENAME ".new"} {print>f}' file1 file2 file3

运行此操作后,文件file1.newfile2.newfile3.new将以新形式传输,并传输一行。当然,您不限于三个文件:您可以在命令行中指定任意数量的文件。

实施例

为了简化我们的示例,让我们只删除前两行而不是15行。考虑这些测试文件:

$ cat file1
1
2
3
$ cat file2
4
5
6
7
8
$ cat file3
9
10
11
12
13
14
15

以下是运行我们命令的结果:

$ awk 'NR==1 || FNR==3{close(f); f=FILENAME ".new"} {print>f}' file1 file2 file3
$ cat file1.new
1
2
3
4
5
$ cat file2.new
6
7
8
9
10
$ cat file3.new
11
12
13
14
15

如您所见,每个文件的前两行已传输到前一个文件。

如何运作

awk逐行隐式读取每个文件。我们的代码的工作是根据行号选择应该写入哪一行的新文件。变量f将包含我们要写入的文件的名称。

  • NR==1 || FNR==16{f=FILENAME ".new"}

    当我们正在阅读第一个文件的第一行NR==1时,或者当我们正在阅读我们所处的文件的第16行FNR==16时,我们将f更新为是添加到.new的当前文件的名称。

    对于简短示例,我们使用了相同的代码,而FNR==16替换为FNR==3

  • print>f

    这会将当前行打印到文件f

    (如果这是一个shell脚本,我们会使用>>。这不是一个shell脚本。这是awk。)

使用glob指定文件名

destination='media/user/directory/'
awk 'NR==1 || FNR==16{close(f); f=FILENAME ".new"} {print>f}'  "$destination"*.ascii

答案 1 :(得分:1)

您可以将之前的$file3值存储在变量中(并检查它是否不是第一次使用-z检查):

#!/bin/bash

destination='media/user/directory/'
prev=""
for file1 in $destination*.ascii
do
    echo $file1
    file2="${file1}.end"
    file3="${file1}.snip"
    sed -e '16,$d' $file1 > $file2
    sed -e '1,15d' $file1 > $file3
    if [ -z "$prev" ]; then
       cat $prev $file2 > outfile
    fi
    prev=$file3
done

答案 2 :(得分:1)

你的任务并不困难。您希望收集目录中所有_end个文件的列表(使用for循环和globbing,而不是循环ls的结果。获得所有end文件后,您只需使用参数展开w / substing remove 解析日期为d1d2以及日期1和日期2:

stuff_20090413T235945_20090414T235944_end
     |    d1  |      |    d2  |

然后,您只需将1中的d1减去date0或d0,然后使用{{1}从d0d1构建以前的文件名而不是_snip。然后只测试前一个_end文件名是否存在,如果存在,则将您当前的_snip文件中的信息粘贴到上一个_end文件中。 e.g。

_snip

测试输入文件

#!/bin/bash

for i in *end; do         ## find all _end files
    d1="${i#*stuff_}"     ## isolate first date in filename
    d1="${d1%%T*}"
    d2="${i%T*}"          ## isolate second date
    d2="${d2##*_}"
    d0=$((d1 - 1))        ## subtract 1 from first, get snip d1
    prev="${i/$d1/$d0}"   ## create previous 'snip' filename
    prev="${prev/$d2/$d1}"
    prev="${prev%end}snip"
    if [ -f "$prev" ]     ## test that prev snip file exists
    then
        printf "paste to : %s\n" "$prev"
        printf "    from : %s\n\n" "$i"
    fi
done

示例使用/输出

$ ls -1
stuff_20090413T235945_20090414T235944_end
stuff_20090413T235945_20090414T235944_snip
stuff_20090414T235945_20090415T235944_end
stuff_20090414T235945_20090415T235944_snip
stuff_20090415T235945_20090416T235944_end
stuff_20090415T235945_20090416T235944_snip
stuff_20090416T235945_20090417T235944_end
stuff_20090416T235945_20090417T235944_snip
stuff_20090417T235945_20090418T235944_end
stuff_20090417T235945_20090418T235944_snip
stuff_20090418T235945_20090419T235944_end
stuff_20090418T235945_20090419T235944_snip

(当然用您的实际前缀替换$ bash endsnip.sh paste to : stuff_20090413T235945_20090414T235944_snip from : stuff_20090414T235945_20090415T235944_end paste to : stuff_20090414T235945_20090415T235944_snip from : stuff_20090415T235945_20090416T235944_end paste to : stuff_20090415T235945_20090416T235944_snip from : stuff_20090416T235945_20090417T235944_end paste to : stuff_20090416T235945_20090417T235944_snip from : stuff_20090417T235945_20090418T235944_end paste to : stuff_20090417T235945_20090418T235944_snip from : stuff_20090418T235945_20090419T235944_end

如果您有疑问,请告诉我。