使用`paste`并了解输入文件名

时间:2016-08-11 08:41:32

标签: bash paste

假设我有文件:foo.tsvbar.tsv,其内容如下所示:

foo.tsv
1
2
3
4
5

bar.tsv
a
b
c
d
e

如果我运行paste foo.tsv bar.tsv > foo_bar.tsv,我会:

foo_bar.tsv
1    a
2    b
3    c
4    d
5    e

虽然这非常好,但我想自动命名foo_bar.tsv以消除误导文件的可能性,例如在拼写错误的情况下。

让我们说:

paste foo.tsv baz.tsv > foo_bar.tsv # foo_bar should have been foo_baz here.

在2个输入的简单情况下很难出错,但如果我这样做:

paste foo.tsv baz.tsv bar.tsv baz.tsv > foo_baz_bar_baz.tsv

事情可能会变得混乱。

有没有办法自动命名输出文件?如何让重定向操作员知道其输入?!

2 个答案:

答案 0 :(得分:4)

您可以使用数组来跟踪所需的文件paste

files=("foo.tsv" "bar.tsv")

然后,paste "${files[@]}"将展开为paste "foo.tsv" "bar.tsv"

最后,要重定向到名称基于参数的文件,您可以使用类似

的内容
$ IFS=_
$ echo "${files[*]%.*}"
foo_bar

即,删除从最后一个点到阵列中所有元素的所有内容,然后将它们打印在一起,将内部字段分隔符设置为_

Shell parameter expansion on arrays中描述了对数组中所有元素执行相同操作的内容,并使用${var[*]}将它们打印在一起Bash Reference Manual → Special Parameters(对anishane的赞誉)评论中的建议。)

然后,将paste命令重定向到使用此printf创建的文件:

command > "$(echo "${files[*]%.*}".tsv)"

所有在一起:

files=("foo.tsv" "bar.tsv")
paste "${files[@]}" > "$(IFS=_; echo "${files[*]%.*}".tsv)"

答案 1 :(得分:3)

您还可以设置一个功能,为您完成大部分工作

pastefile(){

    for i in "$@";do
       newfile+="${i%.*}_"
    done
    ext="${1##*.}"

    paste "$@" > "${newfile%_}.${ext}"

}

运行
$ pastefile foo.tsv bar.tsv
$ cat foo_bar.tsv

1       a
2       b
3       c
4       d
5       e

也可以使用带空格的文件名。