Simple HTTP file sharing in bash

Just a little bash function inspired by a post[1], that allows to quickly share file(s) over the network using a one-shot HTTP request. It only requires nc to bind the listening socket.

function share() {
    ! type -a nc &>/dev/null && { echo "This machine doesn't have 'nc'" >/dev/stderr ; return 1 ; }
    [[ $# -ne 1 ]] && { echo "Usage: share <filename>" >/dev/stderr ; return 1 ; }
    [[ ! -f $1 ]] && { echo "No such file : $1" >/dev/stderr ; return 1 ; }
    port=$((8000 + RANDOM%1000))
    if [[ $OSTYPE == "linux-gnu" ]] ; then
        while read ip ; do echo "http://$ip:$port/$1" ; done < <(/sbin/ip addr ls | awk '/inet / {split($2,a,"/");print a[1];}' | sort -n | uniq)
        cat - "$1" <<- EOF | $(type -p nc) -l -p $port -q 0
            HTTP/1.1 200 OK\r
            Content-Length: $(stat -c %s "$1")
            Content-Type: $(file -b --mime-type "$1")
EOF
    # Check André's comment
    elif [[ $OSTYPE == "darwin*" ]] ; then
        ifconfig -u | \
            sed -ne 's/.*inet \([0-9.]*\) netmask .*/\1/p' | \
            sort -nu | while read ip ; do echo "http://$ip:$port/$1" ; done
    cat - "$1" < < EOF | nc -l "$port"
        HTTP/1.1 200 Ok
        Content-Type: application/octet-stream
        Content-Length: $(eval $(stat -s "$1") && echo $st_size)
EOF
    else
        echo "Please provide a patch for other flavor of Linux/*BSD: <contact@floriancrouzat.net>" && return 1
    fi
}

[1] – http://www.vidarholen.net/contents/blog/?p=17

4 comments so far.

  1. In some environments, you are more likely to have python installed than netcat. If so, this could be useful :
    python -m SimpleHTTPServer
    This will share the current directory on port 8000

    http://www.commandlinefu.com/commands/view/71/serve-current-directory-tree-at-httphostname8000

    Obviously, this is more CPU/RAM intensive than a simple netcat command, but it depends on what you want to achieve…

    • nc and netcat are not the same binary, even if they share some common history ;)
      My initial goal, when I “wrote” that as a student, was to provide a simple, lightweight and one-shot way to share resources across the lab without NFS/SMB/*FTP/ or emailing. Ayway, I wasn’t aware of this python stuff, well, I’m not aware of anything when it comes to python, except that indentation matters… Thanks for the suggestion !

  2. This shell script works on MacOS X / Darwin.
    I used sed rather than awk because that’s what I know better.
    If you want to merge the scripts, OSTYPE is darwin13 (on Mac OS 10.9).

    #!/bin/bash
    ! type -a nc &>/dev/null && [[ $# -ne 1 ]] && [[ ! -f "$1" ]] && port=$((8000 + RANDOM%1000))
    
    ifconfig -u | \
      sed -ne 's/.*inet \([0-9.]*\) netmask .*/\1/p' | \
      sort -nu | \
      while read ip ; do
        echo "http://$ip:$port/$1"
      done
    
    cat - "$1" < < EOF | nc -l "$port"
    HTTP/1.1 200 Ok
    Content-Type: application/octet-stream
    Content-Length: $(eval $(stat -s "$1") && echo $st_size)
    
    EOF
    

Share your thoughts

*