使用“粘贴”并了解输入文件名

Using the `paste` and being aware of input filenames

假设我有文件: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

事情可能会变得一团糟。

有没有自动命名输出文件的方法?我怎样才能让重定向运算符知道它的输入?!

您可以使用数组来跟踪要 paste 在一起的文件:

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

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

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

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

也就是说,删除从最后一个点到数组中所有元素的所有内容,然后将它们一起打印,将内部字段分隔符设置为 _

and printing them together using ${var[*]} is described in Bash Reference Manual → Special Parameters (kudos to anishane 中描述了对数组中的所有元素执行相同的操作以获取评论中的建议。

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

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

总计:

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

您还可以设置一个函数来为您完成大部分工作

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

也适用于带空格的文件名。