【问题标题】:How can a bash script write out a binary file, without using uudecode?bash 脚本如何在不使用 uudecode 的情况下写出二进制文件?
【发布时间】:2011-03-08 12:38:23
【问题描述】:

我在这里为 bash 脚本专家准备了一些难题……我有一个 bash 脚本,它需要在运行时创建一个小的(80 字节)二进制文件。文件的内容需要包含在脚本本身中(即我不想将文件与脚本一起打包)。

我的脚本目前是这样的:

echo 'begin-base64 644 dummy.wav' > /tmp/dummy.uu
echo 'UklGRkgAAABXQVZFZm10IBAAAAADAAEAAHcBAADcBQAEACAAZmFjdAQAAAAAAAAAUEVBSxAAAAAB' >> /tmp/dummy.uu
echo 'AAAAQDYlTAAAAAAAAAAAZGF0YQAAAAA=' >> /tmp/dummy.uu
echo '====' >> /tmp/dummy.uu
uudecode -o /tmp/dummy.wav /tmp/dummy.uu
rm /tmp/dummy.uu

...在上述运行之后,我有我的文件 /tmp/dummy.wav。但是我刚刚发现要运行这个脚本的计算机没有安装 uudecode (我不允许安装它),所以我需要找到其他方法来创建这个文件。有什么想法吗?

【问题讨论】:

    标签: bash scripting binary uudecode


    【解决方案1】:

    一些安装程序会做类似的事情:

    #!/bin/bash
    tail -n +4 $0 | tar xvzf -
    exit
    <tgz file appended here><newline>
    

    【讨论】:

      【解决方案2】:

      在脚本末尾添加exit,将文件附加到脚本末尾,然后使用tail -c 80 获取内容。只要您不需要担心换行符转换问题,这将起作用。

      【讨论】:

        【解决方案3】:

        如果目标计算机有perl 可用:

        perl -ne 'print unpack("u",$_)' > dummy.wav <<EOD
        M4DE&1D@```!7059%9FUT(!`````#``$``'<!``#<!0`$`"``9F%C=`0`````
        C````4$5!2Q`````!````0#8E3```````````9&%T80``````
        EOD
        

        这是使用您在原始计算机上执行 uuencode dummy.wav &lt; dummy.wav 所获得的非 base64 格式。

        如果做不到这一点,您总是可以这样做:

        echo -ne '\x52\x49\x46\x46\x48\x00\x00\x00'  > dummy.wav
        echo -ne '\x57\x41\x56\x45\x66\x6d\x74\x20' >> dummy.wav
        echo -ne '\x10\x00\x00\x00\x03\x00\x01\x00' >> dummy.wav
        echo -ne '\x00\x77\x01\x00\x00\xdc\x05\x00' >> dummy.wav
        echo -ne '\x04\x00\x20\x00\x66\x61\x63\x74' >> dummy.wav
        echo -ne '\x04\x00\x00\x00\x00\x00\x00\x00' >> dummy.wav
        echo -ne '\x50\x45\x41\x4b\x10\x00\x00\x00' >> dummy.wav
        echo -ne '\x01\x00\x00\x00\x40\x36\x25\x4c' >> dummy.wav
        echo -ne '\x00\x00\x00\x00\x00\x00\x00\x00' >> dummy.wav
        echo -ne '\x64\x61\x74\x61\x00\x00\x00\x00' >> dummy.wav
        

        这一点 bash 是通过以下方式生成的:

        $ hexdump -e '"echo -ne '\''" 8/1 "x%02x" "'\'' >> dummy.wav\n"' dummy.wav | sed 's;x;\\x;g;1s/>/ /'
        

        编辑添加: 正如这里的回复中指出的那样,这样的事情也是一种可能性:

        xargs -d'\n' -n1 echo -ne > dummy.wav <<EOD
        \x52\x49\x46\x46\x48\x00\x00\x00\x57\x41\x56\x45\x66\x6d\x74\x20
        \x10\x00\x00\x00\x03\x00\x01\x00\x00\x77\x01\x00\x00\xdc\x05\x00
        \x04\x00\x20\x00\x66\x61\x63\x74\x04\x00\x00\x00\x00\x00\x00\x00
        \x50\x45\x41\x4b\x10\x00\x00\x00\x01\x00\x00\x00\x40\x36\x25\x4c
        \x00\x00\x00\x00\x00\x00\x00\x00\x64\x61\x74\x61\x00\x00\x00\x00
        EOD
        

        -d 参数对于关闭 xargs 自己的反斜杠处理很重要)

        您还可以将我的 hexdump 命令中的 8/1 转换为 80/1 并有一个很长的 echo 行。

        【讨论】:

        • 您可以使用与带有转义十六进制值的 Bash 版本相同的 here doc 功能,并避免所有这些回声和 &gt;&gt; 附加。
        • 使用 here-doc 添加了一个版本,没有 &gt;&gt;
        【解决方案4】:

        在我看来 uuencode 和 uudecode 是必不可少的,但是 这只是我的意见。 在不创建临时文件的情况下,您也可以做一些事情 像这样(uudecode.sh):

        #!/bin/bash
        # --
        # -- Uudecoding without using a regular temporary file
        # --
        
        # -- Create a named pipe:
        mknod /tmp/.dummypipe p
        
        # -- Starting uudecoding on that pipe in the background:
        uudecode -o dummy.txt /tmp/.dummypipe &
        
        # -- Push base64-uuencoded content into the named pipe:
        cat <<END_DUMMY > /tmp/.dummypipe
        begin-base64 644 dummy.txt
        VGhpcyBpcyB0aGUgdXVkZWNvZGVkIHRleHQuCg==
        ====
        END_DUMMY
        
        # -- Remove the named pipe
        rm /tmp/.dummypipe
        

        【讨论】:

        • OP说他没有uudecode,你的脚本使用uudecode。
        【解决方案5】:

        这是解码 radix 64 格式数据的另一个示例,它运行缓慢,但功能齐全。

        #!/bin/bash
        exec<$0
        while read line ; do if [ "$line" = "#payload" ] ; then break; fi; done
        r64='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
        i=0; while [ $i -lt 256 ] ; do tab[$i]=-1 ; let i=$i+1 ;done
        i=0; while [ $i -lt 64 ] ; do tab[`printf "%d" "'${r64:$i:1}"`]=$i ; let i=$i+1; done
        bi=0
        while read -n 1 x
        do
         in=${tab[`printf "%d" "'$x"`]}
         if [ $in -ge 0 ]; then case $bi in
          0 ) out=$(($in<<2)); bi=6 ;;
          2 ) out=$(($out|$in)); printf \\$(printf '%03o' $(($out&255)) ); bi=0 ;;
          4 ) out=$(($out+($in>>2))); printf \\$(printf '%03o' $(($out&255)) );
          bi=0; out=$(($in<<6)); bi=2 ;;
          * ) out=$(($out+($in>>4))); printf \\$(printf '%03o' $(($out&255)) );
          bi=0; out=$(($in<<4)); bi=4 ;;
          esac fi
        done
        exit
        #payload
        dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2XmAgICAte3Z2dnZ2dnZ2dnZ2dnZ2dgp2dnZ2dnZ2dnZ2dnZ2dnZ2PiAg
        ICAgIC4gLXZ2dnZ2dnZ2dnZ2dnZ2CnZ2dnZ2dnZ2dnZ2dnZ2dn0gICAgICAgPT4gLXZ2dnZ2dnZ2dnZ2
        dnYKdnZ2dnZJdnZJdnZJdnZJOyAgICAgICAtICAgPXZJdkl2dkl2dkl2dgp2dnZ2SXZ2dnZ2dnZ2dnZg
        ICAgICAgICAgICAgbnZ2dnZJdnZ2dnZ2CnZ2dnZ2dnZ2SXZJdnZJdiAgIC4gICAgICwgICA8dnZ2SXZ2
        dkl2dkkKdnZ2SXZ2SXZ2dnZ2SXZJIF9zOyAgX3VvLyAgID12dnZ2dnZ2dnZJdgp2dnZ2dkl2dnZJdnZ2
        dnYgdyRtICBtQCRtICAgPXZ2dnZJdnZJdnZ2CnZ2dnZJdnZ2dnZ2dkl2SSBmPTQuO1cgYFE7ICA9dnZ2
        dnZ2dnZ2dnYKdnZ2SXZ2dnZJdnZJdnZ2IHQtM3MlJiAgbWAgID12dnZ2SXZJdnZJdgp2dnZ2dnZ2SXZ2
        dnZ2dnYgXWlvWjZYYXVQICAgPXZ2dnZ2dnZ2SXZ2CnZ2dkl2dkl2dnZJdnZJdi4pbVojWlojWlMgICAu
        dnZ2SXZJdnZ2dnYKdnZ2dnZ2dnZ2dnZ2SXZ2OjNYWlpaI1pTWCAgICB7dnZ2dnZ2dkl2dgp2dnZ2SXZ2
        SXZ2SXZ2dnY7PFNYWlhTZFhuIC5pLj12dnZJdnZJdnZ2CnZ2dkl2dnZ2dkl2dnZ2dmBdJVhYWlhubW0+
        IC1gIHZ2dnZ2dnZ2dnYKdnZ2dnZ2SXZ2dnZ2SXYlIGptdklud1FXUW0gICAgPHZ2SXZ2SXZ2SQp2dnZJ
        dnZ2dkl2dkl2dmAuUVFvWG1tUVFRUWMgICAge0l2dnZ2dnZ2CnZ2dnZ2dkl2dnZ2dnYrIGpRV1FtV1FR
        UVFRayAgICAtdnZ2dkl2dkkKdnZ2dkl2dnZ2SXZJPiBfUVFRUVFRUVFRUVFRLiAgICA9dkl2dnZ2dgp2
        dnZJdnZ2SXZ2dmwgIF1RUVFRV1FRUVdXOCRMICAgICA8dnZ2SXZ2CnZ2dnZ2dnZ2dnZ2OyAgbm1RUVFt
        UVFRbXdvb20gLiAgIC1JdnZ2dnYKdnZ2SXZ2SXZ2SX0gID1RV1FRUVFRUVFRUVFtMlsgLSAgID12dkl2
        dgp2dnZ2dnZ2dkl2Oy4gZFFRUVFRUVFRUVFRUVFRcSAgLiAgIEl2dnZ2CnZ2dnZJdkl2dnZgLjxRUVFR
        UVFRUVFRUVFRUVdRKC4uLiAgPEl2dnYKdnZ2SXZ2dnZ2PiAgZFFRUVFRUVFRUVFRUVFRUVFbICAuICAg
        dnZ2SQp2dnZ2dnZ2dnYnIC5RUVFRUVFRUVFRUVFRUVFRUWsgIC4gICB7dnZ2CnZ2dkl2dkl2PiAuXVFR
        UVFRV1dXUVFRUVFRUVFRbSAgICAgIClsdnYKdnZ2dnZ2dnZgIDpqUVFRUVEjUVdRUVFRUVFRUVFXICAu
        ICAgOnZ2SQp2dnZ2SXZ2bCAgOmpXUVFRUUVXV1FRUVFRV1FRUVcgIGAgICA6dnZ2CnZ2dkl2dnZJLl86
        alFRUVFRRVdRUVFRUVFRUVFRVyAuIC4uID12dnYKdnZ2dnZ2dnZkIzYvUVdRUVFFUVFRUVFRUVFRV1dM
        LiAgIDogKXZ2dgp2dnZJdnZJMyNaWkwtJFFRUVFRV1FRUVFRUVFCWiNgICAgLmRvdnZ2CnZ2dnZ2SXZa
        IyMjWj4tNFFRUVdRUVFRUVFRUUVaay4gICBqWlh2dnYKdnZ2dndvbVgjWiNaIy4gNFFRUVFRUVFRUVdX
        MVpYc189dVhaaHZ2dgp2dnZaWiNaI1VVWiNaTCAgXVFRUVFRUVFRUVdlWFpYcVhtWiNVenZ2CnZ2SVgj
        I1ojWiMjWiNaLyAuUVFRUVFRUVFRVzEzI1paWlojWiMjb3YKdnZ2ZFVaIyNVWiMjVVVoX2FRUVFRUVFR
        UVFQOlhaIyNVI1ojVVojaAp2dklkIyNaI1ojI1ojWlpaV1FRUVFRUVFXUCA9ZFojWiNaIyNaIyNaCnZ2
        dlojWiMjVVVaI1ojWlpKUVFRUVFXUF4gIClYIyNaI1VVWiNVWjEKdnZ7WlojWlVaIyNaIyNaVXMtIT8i
        fiAgICAgdlgjWiMjWiNaWF5sdgp2bCBZWFhYWFpaVVUjWlpaMS4gICAgICAgICB2WFojWiNaWCIgIDx2
        CnZzICAtfiJJMVhYWFpaWm8xICAgICAgICAgIEluWFhaU31gICAgPHYKdnY7ICAgICAtLTwxMjIxbGAg
        ICAgICAgICAgPElubjF9ICAgICB2SQp2dmwsICAgICAgICB+Kz5gICAgICAgICAgICAgfnwrfiAgICAu
        JUl2CnZ2dnZpLiAgICAgICAgICAgIF9pc2ksICAgICAgICAgICAgX3ZJdnYKdnZ2dnZ2c19fXy4uLi5f
        XyV2dnZ2SXZpLCxfLiAuLl9fPnZ2dnZ2dgp2dnZ2SXZ2dm52dnZ2dnZudnZ2dnZ2dnZubnZ2dnZ2dnZ2
        dnZ2dnZ2Cg==
        

        【讨论】:

          【解决方案6】:
          #!/bin/bash
          
          # Define usage help
          usage () {
              echo -e "USAGE:\n\t$0 <file to create> <dir to tar> <name of script or command to run>\n"
              exit 0
          }
          
          # check commandline arguments
          if [ "$1" = "-h" ]; then usage; fi
          if [ -z $1 ]; then usage; fi
          if [ -z $2 ]; then usage; fi
          if [ -z $3 ]; then usage; fi
          
          # test for the directory and if it exists, create the bin file using tar
          if [ -d "$2" ]; then
              cat >$1<<EOF
          #!/bin/sh -e
          sed -e '1,/^exit$/d' "\$0" | tar xzf - && "./$2/$3"
          exit
          EOF
              tar czf - $2 >> $1
          else
              echo "$2 does not exist, aborting!"
              exit 1
          fi
          
          # make the new file executable and exit
          chmod +x $1
          exit 0
          

          【讨论】:

          • 如果你把这个例子简化为编写二进制文件的基本要素,并解释它的作用和工作原理,这个例子会更好。
          【解决方案7】:

          我会使用 base64 编码,因为这似乎是 uu 编码的一般替代品,并且操作原理非常相似。

          【讨论】:

          • 欢迎来到 Stack Overflow 并感谢您的贡献。然而,这并不是一个完整的答案。解释您将使用哪些命令来解码文件将大大有助于改进它。工作示例代码会更好。
          【解决方案8】:

          只需将二进制数据编码为 base64 并执行以下操作:

          #! /bin/bash
          
          cat <<EOF | base64 -d > wherever-it-goes.bin
          UtEOtUaZcUCrEJtPJrA34BH8Wdpxb1/DtfMo5syiE/h+moNyApEkg2ZwA2/jTDdfl4WijnNbMzvZ
          RrF3i7X353AjmTjLBz1NcOOJJhRPYLJ4WQYONyYj/fAhnXQd+s4SHaNponOWKj1AAzdlJY1VLWaX
          P8QBJQcn2FTL4pJ3N04=
          EOF
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-12-06
            • 2011-07-31
            • 1970-01-01
            • 1970-01-01
            • 2020-10-13
            • 1970-01-01
            相关资源
            最近更新 更多