如何在bash中的源函数中的scp命令中正确地转义形成多个文件的空格

时间:2018-12-19 17:08:05

标签: bash escaping scp

我在.bashrc中构建了一个函数,当它试图对名称中带有空格的scp文件进行破坏时,该函数会中断,但是如果我直接在shell中运行该函数生成的命令输出,那似乎可以正常工作。 / p>

我尝试了转义空格以及单引号和双引号的几种变体,下面的版本是我最接近使用的版本,我不知道为什么它会失败。

来自.bashrc

push2() {
    # parse args, build file list, get suffix from final arg
    files=""
    i=1
    orig_IFS=$IFS; IFS=":"
    for arg in $*; do
        if [ "$i" = "$#" ]; then
            suffix=$arg
        else
            files="$files $(echo $arg | sed -r 's/ /\\ /')" #escape spaces
        fi
        i=$(($i+1))
    done
    IFS=$orig_IFS
    # determine prefix and proxy
    gen_prefix $suffix
    # output generated command for debugging
    echo "scp $scp_proxy$files testuser@$prefix$suffix:"
    # run command
    scp $scp_proxy$files testuser@$prefix$suffix:
}

即使输出命令字符串似乎已正确转义,运行函数似乎仍然失败

root@DHCP-137:~$ push2 temp* 42
scp  temp temp\ file testuser@10.3.3.42:
temp                                          100% 6008     1.1MB/s   00:00 
temp\: No such file or directory
file: No such file or directory

运行它生成的命令可以正常工作

root@DHCP-137:~$ scp  temp temp\ file testuser@10.3.3.42:
temp                                          100% 6008   896.4KB/s   00:00 
temp file                                     100%    0     0.0KB/s   00:00 
root@DHCP-137:~$ 

其他信息:GNU bash,版本4.4.12(1)-发行版(x86_64-pc-linux-gnu)-在Debian 9上运行

2 个答案:

答案 0 :(得分:3)

首先,更改您的呼叫签名,以使后缀为 first



    import networkx as nx
    from networkx.algorithms.community import greedy_modularity_communities
    # Insert Dataset
    G = nx.read_edgelist("p120.txt")
    #Print information Graph
    print("Number Nodes: ",G.number_of_nodes())
    print("Number Edges: ",G.size())
    # Community detection algorithm
    c = list(greedy_modularity_communities(G))
    print("Number of  community: ",len(c))
    print ("Running time: ",int(T.total_seconds()),"second!")
    i=0
    running=True
    while running:
        if i == len(c):
            break
        # n is number of node in the community.
        n=len(c[i])
        #create Graph in community
        results = [int(m) for m in c[i]]
        print("community",i,":",results)
        Com_of_graph=nx.Graph()
        Com_of_graph.add_nodes_from(results)
        number_of_com_node=Com_of_graph.number_of_nodes()
        print("Node of community: ",number_of_com_node)
        for j in range(number_of_com_node-1):
            for k in range(number_of_com_node-1):
                u=results[j]
                v=results[k]
                if G.number_of_edges(str(u),str(v))>0:
                    u1=list()
                    v1=list()
                    r=u1.append(u)
                    s=v1.append(v)
                    print(r)
                    print(s)
           z=zip(r,s)
       Com_of_graph.add_edges_from(*z)
       i=i+1

然后将函数定义为

push2 42 ./temp*

push2 () { local -a scpProxy local prefix suffix suffix=$1 shift gen_prefix "$suffix" scp "${scpProxy[@]}" "$@" "testuser@$prefix.$suffix:" } 看起来像

gen_prefix

调用gen_prefix () { case $1 in 42) scpProxy=() prefix=10.3.3 ;; 89) scpProxy=(-o ProxyJump=user@server) prefix=123.456.789 ;; esac } 之后,shift仅包含您要传输的文件。 $@是一个数组,其中包含多个要传递给scpProxy的单独参数;如果为空,则scp将扩展为0个参数,而不是空字符串。

(使用"${scpProxy[@]}"而不是./temp*可以防止包含temp*的匹配项,因此可能被误认为是远程文件名。)

尽管:似乎是“全局”定义其变量,但实际上只是在gen_prefix使用动态范围界定的gen_prefix被称为 的范围内定义它们,而不是像大多数其他通用语言一样的词法作用域)。对bash的两次调用可确保local分配的内容保留在gen_prefix内,并且在push2退出后不可见。


作为附加说明,使用适当的push2配置可以取消许多此功能。在您的ssh文件中考虑以下问题:

.ssh/config

现在您根本不需要Host somehost User testuser Hostname 10.3.3.42 Host someotherhost User testuser Hostname 123.456.789.89 ProxyJump user@server ;刚运行

push2

scp temp* somehost:

,正确的地址和选项将被自动使用。 scp temp* someotherhost: 配置取代了ssh所做的所有事情,并且无需调用gen_prefix,因此不再需要包装gen_prefix

答案 1 :(得分:-1)

通过更改最后一行来修复整个问题

scp $scp_proxy$files testuser@$prefix$suffix:

并像这样将其包装在评估中

eval "scp $scp_proxy$files testuser@$prefix$suffix:"