我有兴趣根据数字编号连接多个文件,并删除第一行。
e.g。 chr1_smallfiles然后chr2_smallfiles然后chr3_smallfiles ....等(每个没有标题)
请注意chr10_smallfiles
需要chr9_smallfiles
之后 - 也就是说,这需要是数字排序顺序。
当将两个命令awk和ls -v1分开时,每个命令都正常工作,但是当它们放在一起时,它不起作用。请帮助谢谢!
awk 'FNR>1' | ls -v1 chr*_smallfiles > bigfile
答案 0 :(得分:3)
问题在于您尝试将文件列表传递给awk的方式。此刻,你将awk的输出管道输出到ls,这没有任何意义。
请记住,正如评论中所提到的,ls是一种交互式使用的工具,一般来说,它的输出不应该被解析。
如果排序不是问题,您可以使用:
awk 'FNR > 1' chr*_smallfiles > bigfile
shell会将glob chr*_smallfiles
扩展为一个文件列表,这些文件作为参数传递给awk。对于每个文件名参数,将打印除第一行之外的所有文件。
由于您要对文件进行排序,因此事情并非如此简单。如果您确定存在所有文件,请在原始命令中将chr*_smallfiles
替换为chr{1..99}_smallfiles
。
使用一些特定于Bash和GNU的排序功能,您还可以实现如下排序:
printf '%s\0' chr*_smallfiles | sort -z -n -k1.4 | xargs -0 awk 'FNR > 1' > bigfile
printf '%s\0'
打印每个文件名后跟一个空字节sort -z
对以空字节分隔的记录进行排序-n -k1.4
进行数字排序,从第4个字符开始(文件名的数字部分)xargs -0
将排序的,以null分隔的输出作为参数传递给awk 否则,如果你想按数字顺序浏览文件,并且你不确定是否所有文件都存在,那么你可以使用shell循环(尽管它会明显慢于a)单awk调用):
for file in chr{1..99}_smallfiles; do # 99 is the maximum file number
[ -f "$file" ] || continue # skip missing files
awk 'FNR > 1' "$file"
done > bigfile
答案 1 :(得分:2)
您还可以使用tail
连接所有没有标题
tail -q -n+2 chr*_smallfiles > bigfile
如果您想按照质询中的描述以自然排序顺序连接文件,则可以使用
ls -v1的结果传递给xargs
>
ls -v1 chr*_smallfiles | xargs -d $'\n' tail -q -n+2 > bigfile
(感谢Charles Duffy)xargs -d $'\n'
将分隔符设置为换行符\n
,以防文件名包含空格或引号
答案 2 :(得分:2)
使用bash 4关联数组仅提取每个文件名的数字子字符串;单独排序;然后在生成的顺序中检索并连接全名:
#!/usr/bin/env bash
case $BASH_VERSION in ''|[123].*) echo "Requires bash 4.0 or newer" >&2; exit 1;; esac
# when this is done, you'll have something like:
# files=( [1]=chr_smallfiles1.txt
# [10]=chr_smallfiles10.txt
# [9]=chr_smallfiles9.txt )
declare -A files=( )
for f in chr*_smallfiles.txt; do
files[${f//[![:digit:]]/}]=$f
done
# now, emit those indexes (1, 10, 9) to "sort -n -z" to sort them as numbers
# then read those numbers, look up the filenames associated, and pass to awk.
while read -r -d '' key; do
awk 'FNR > 1' <"${files[$key]}"
done < <(printf '%s\0' "${!files[@]}" | sort -n -z) >bigfile
答案 3 :(得分:1)
你可以使用下面的for循环,这对我有用: -
for file in chr*_smallfiles
do
tail +2 "$file" >> bigfile
done
它将如何运作? for循环使用wild chard character *
chr*_smallfiles
读取当前目录中的所有文件,并将文件名分配给变量file
,tail +2 $file
将输出该文件的所有行,除了第一行并附加到文件bigfile
中。所以最后所有文件都会合并(接受每个文件的第一行)到一个文件bigfile
。
答案 4 :(得分:0)
为了完整起见,sed
解决方案怎么样?
for file in chr*_smallfiles
do
sed -n '2,$p' $file >> bigfile
done
希望它有所帮助!