├── .gitignore
├── circle.yml
├── Makefile
├── test
└── transfer
├── README.md
└── src
└── transfer
/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | dependencies:
2 | pre:
3 | - sudo add-apt-repository ppa:duggan/bats -y
4 | - sudo apt-get update
5 | - sudo apt-get install bats
6 |
7 | test:
8 | override:
9 | - make test
10 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .DEFAULT_GOAL := stub
2 | bindir ?= ./build/bin
3 |
4 | clean: | uninstall
5 |
6 | install: | stub
7 | @rsync -a src/ ${bindir}/
8 |
9 | stub:
10 | @mkdir -p ${bindir}
11 |
12 | test: | install
13 | @bats test/transfer
14 |
15 | uninstall:
16 | @rm -rf ${bindir}
17 |
18 | .PHONY: clean install stub test uninstall
19 |
--------------------------------------------------------------------------------
/test/transfer:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | @test 'upload via arguments should succeed' {
4 | run bash -c 'build/bin/transfer upload src/transfer 2> /dev/null'
5 | [ ${status} -eq 0 ]
6 | [ $(expr "${output}" : '^https://transfer.sh/[a-zA-Z0-9]*/transfer$') -gt 0 ]
7 | }
8 |
9 | @test 'upload with slug via arguments should succeed' {
10 | run bash -c 'build/bin/transfer upload src/transfer foo 2> /dev/null'
11 | [ ${status} -eq 0 ]
12 | [ $(expr "${output}" : '^https://transfer.sh/[a-zA-Z0-9]*/foo$') -gt 0 ]
13 | }
14 |
15 | @test 'upload via options should succeed' {
16 | run bash -c 'build/bin/transfer upload --file src/transfer 2> /dev/null'
17 | [ ${status} -eq 0 ]
18 | [ $(expr "${output}" : '^https://transfer.sh/[a-zA-Z0-9]*/transfer$') -gt 0 ]
19 | }
20 |
21 | @test 'upload with slug via options should succeed' {
22 | run bash -c 'build/bin/transfer upload --file src/transfer --slug foo 2> /dev/null'
23 | [ ${status} -eq 0 ]
24 | [ $(expr "${output}" : '^https://transfer.sh/[a-zA-Z0-9]*/foo$') -gt 0 ]
25 | }
26 |
27 | @test 'upload from pipe should succeed' {
28 | run bash -c 'cat src/transfer | build/bin/transfer upload --slug transfer 2> /dev/null'
29 | [ ${status} -eq 0 ]
30 | [ $(expr "${output}" : '^https://transfer.sh/[a-zA-Z0-9]*/transfer$') -gt 0 ]
31 | }
32 |
33 | @test 'upload of directory should succeed' {
34 | run bash -c 'build/bin/transfer upload src transfer.tar.gz 2> /dev/null'
35 | [ ${status} -eq 0 ]
36 | [ $(expr "${output}" : '^https://transfer.sh/[a-zA-Z0-9]*/transfer.tar.gz$') -gt 0 ]
37 | }
38 |
39 | @test 'download to file should succeed' {
40 | local up=$(build/bin/transfer upload src/transfer 2> /dev/null)
41 | run bash -c "build/bin/transfer download "${up}" build/.download 2> /dev/null"
42 | [ ${status} -eq 0 ]
43 | }
44 |
45 | @test 'download to pipe should succeed' {
46 | local up=$(build/bin/transfer upload src/transfer 2> /dev/null)
47 | run bash -c "build/bin/transfer download "${up}" 2> /dev/null"
48 | [ ${status} -eq 0 ]
49 | }
50 |
51 | @test '-h should output usage' {
52 | run build/bin/transfer -h
53 | [ ${status} -eq 0 ]
54 | [ "${#lines[@]}" -gt 1 ]
55 | }
56 |
57 | @test '--help should output usage' {
58 | run build/bin/transfer --help
59 | [ ${status} -eq 0 ]
60 | [ "${#lines[@]}" -gt 1 ]
61 | }
62 |
63 | @test '-v should output version' {
64 | run build/bin/transfer -v
65 | [ ${status} -eq 0 ]
66 | [ $(expr "${output}" : 'v*') -ne 0 ]
67 | }
68 |
69 | @test '--version should output version' {
70 | run build/bin/transfer --version
71 | [ ${status} -eq 0 ]
72 | [ $(expr "${output}" : 'v*') -ne 0 ]
73 | }
74 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # transfer-cli | Powerful transfer.sh CLI via pure bash
2 | [](https://github.com/rockymadden/transfer-cli/releases)
3 | [](http://semver.org/)
4 | [](https://guides.github.com/introduction/flow/)
5 | [](https://opensource.org/licenses/MIT)
6 | [](https://www.zenhub.io/)
7 | [](https://rockymadden-slack.herokuapp.com/)
8 | [](https://circleci.com/gh/rockymadden/transfer-cli)
9 |
10 | A pure bash, pipe friendly, encryption capable, feature rich, command line interface for
11 | [transfer.sh](https://transfer.sh).
12 |
13 | __Upload samples:__
14 |
15 | ```bash
16 | $ # From file:
17 | $ transfer upload /path/to/file.log
18 | $ transfer upload --file=/path/to/file.log
19 | $ transfer upload --file /path/to/file.log
20 | $ transfer upload -f /path/to/file.log
21 |
22 | $ # From directory:
23 | $ transfer upload /path
24 | $ transfer upload --file=/path
25 | $ transfer upload --file /path
26 | $ transfer upload -f /path
27 |
28 | $ # From pipe:
29 | $ ls | transfer upload --slug=ls.log
30 | $ ls | transfer upload --slug ls.log
31 | $ ls | transfer upload -s ls.log
32 |
33 | $ # With encryption (symmetric):
34 | $ transfer upload /path/to/file.log --encrypt
35 | $ transfer upload /path/to/file.log -e
36 | $ transfer upload /path/to/file.log --encrypt --password password
37 |
38 | $ # With custom slug:
39 | $ transfer upload /path/to/file.log custom.log
40 | $ transfer upload --file=/path/to/file.log --slug=custom.log
41 | $ transfer upload --file /path/to/file.log --slug custom.log
42 | $ transfer upload -f /path/to/file.log -s custom.log
43 | ```
44 |
45 | __Download samples:__
46 |
47 | ```bash
48 | $ # To file:
49 | $ transfer download https://transfer.sh/abcXYZ/file.log /tmp/file.log
50 | $ transfer download --url=https://transfer.sh/abcXYZ/file.log --file=/tmp/file.log
51 | $ transfer download --url https://transfer.sh/abcXYZ/file.log --file /tmp/file.log
52 | $ transfer download -u https://transfer.sh/abcXYZ/file.log -f /tmp/file.log
53 |
54 | $ # To pipe:
55 | $ transfer download https://transfer.sh/abcXYZ/file.tar.gz | tar xz
56 | $ transfer download --url=https://transfer.sh/abcXYZ/file.tar.gz | tar xz
57 | $ transfer download --url https://transfer.sh/abcXYZ/file.tar.gz | tar xz
58 | $ transfer download -u https://transfer.sh/abcXYZ/file.tar.gz | tar xz
59 |
60 | $ # With decryption (symmetric):
61 | $ transfer download https://transfer.sh/abcXYZ/file.log --decrypt
62 | $ transfer download https://transfer.sh/abcXYZ/file.log -d
63 | $ transfer download https://transfer.sh/abcXYZ/file.log --decrypt --password password
64 | ```
65 |
66 | ## Installation
67 |
68 | ### Via `brew`:
69 |
70 | ```bash
71 | $ brew tap rockymadden/rockymadden
72 | $ brew install transfer-cli
73 | ```
74 |
75 | ### Via `curl`:
76 |
77 | ```bash
78 | $ curl -O https://raw.githubusercontent.com/rockymadden/transfer-cli/master/src/transfer
79 | $ chmod +x transfer
80 | ```
81 |
82 | ### Via `make`:
83 |
84 | ```bash
85 | $ git clone git@github.com:rockymadden/transfer-cli.git
86 | $ cd transfer-cli
87 | $ make install bindir=/path/to/bin
88 | ```
89 |
90 | ## Usage
91 | ```bash
92 | $ transfer --help
93 | Usage:
94 | transfer download [ [file]]
95 | [--decrypt|-d] [--file|-f ] [--password|-p ] [--trace|-x]
96 | [--url|-u ]
97 |
98 | transfer upload [ [slug]]
99 | [--encrypt|-e] [--file|-f ] [--password|-p ] [--slug|-s ]
100 | [--trace|-x]
101 |
102 | Commands:
103 | download Download from transfer.sh to file or piped output
104 | upload Upload a file, directory, or piped input to transfer.sh
105 |
106 | More Information:
107 | chat https://rockymadden-slack.herokuapp.com
108 | repo https://github.com/rockymadden/transfer-cli
109 | ```
110 |
111 | ## License
112 | ```
113 | The MIT License (MIT)
114 |
115 | Copyright (c) 2016 Rocky Madden (https://rockymadden.com/)
116 |
117 | Permission is hereby granted, free of charge, to any person obtaining a copy
118 | of this software and associated documentation files (the "Software"), to deal
119 | in the Software without restriction, including without limitation the rights
120 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
121 | copies of the Software, and to permit persons to whom the Software is
122 | furnished to do so, subject to the following conditions:
123 |
124 | The above copyright notice and this permission notice shall be included in
125 | all copies or substantial portions of the Software.
126 |
127 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
128 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
129 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
130 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
131 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
132 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
133 | THE SOFTWARE.
134 | ```
135 |
--------------------------------------------------------------------------------
/src/transfer:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # COMMAND PARSING #################################################################################
4 | cmd="${1}" ; shift
5 |
6 | # STDIN FRIENDLINESS ##############################################################################
7 | case "${cmd}" in
8 | upload) [ -p /dev/stdin ] && stdin=$(cat <&0) ;;
9 | esac
10 |
11 | # ARGUMENT AND OPTION PARSING #####################################################################
12 | while (( "$#" )); do
13 | case "${1}" in
14 | --decrypt|-d) decrypt=0 ; shift ;;
15 | --encrypt|-e) encrypt=0 ; shift ;;
16 | --file=*) file=${1/--file=/''} ; shift ;;
17 | --file*|-f*) file=${2} ; shift ; shift ;;
18 | --password=*) password=${1/--password=/''} ; shift ;;
19 | --password*|-p*) password=${2} ; shift ; shift ;;
20 | --slug=*) slug=${1/--slug=/''} ; shift ;;
21 | --slug*|-s*) slug=${2} ; shift ; shift ;;
22 | --trace|-x) trace='set -x' ; shift ;;
23 | --url=*) url=${1/--url=/''} ; shift ;;
24 | --url*|-u*) url=${2} ; shift ; shift ;;
25 | *)
26 | case "${cmd}" in
27 | download)
28 | [ -n "${1}" ] && [ -n "${url}" ] && [ -z "${file}" ] && file=${1}
29 | [ -n "${1}" ] && [ -z "${url}" ] && url=${1}
30 | ;;
31 | upload)
32 | [ -n "${1}" ] && [ -n "${file}" ] && [ -z "${slug}" ] && slug=${1}
33 | [ -n "${1}" ] && [ -z "${file}" ] && file=${1}
34 | ;;
35 | esac
36 | shift
37 | ;;
38 | esac
39 | done
40 |
41 | # TRACING #########################################################################################
42 | ${trace}
43 |
44 | # ARGUMENT AND OPTION PROMPTING ###################################################################
45 | case "${cmd}" in
46 | download)
47 | [ -z "${url}" ] && read -e -p 'Enter url (e.g. https://transfer.sh/abcXYZ/file.log): ' url
48 | ;;
49 | upload)
50 | [ -z "${file}" ] && read -e -p 'Enter file (e.g. /path/to/file.log): ' file
51 | ;;
52 | esac
53 |
54 | # COMMAND FUNCTIONS ###############################################################################
55 | function download() {
56 | if [ -n "${file}" ]; then
57 | local path=$(greadlink -f "${file}" 2> /dev/null || readlink -f "${file}" 2> /dev/null)
58 |
59 | curl --progress-bar "${url}" |
60 | ([ -z "${decrypt}" ] && cat || openssl aes-256-cbc -d -a ${password:+-k "${password}"}) > "${path}"
61 |
62 | echo "${path}"
63 | if type pbcopy &> /dev/null; then echo -n ${path} | pbcopy; fi
64 | else
65 | curl --silent "${url}" 2> /dev/null |
66 | ([ -z "${decrypt}" ] && cat || openssl aes-256-cbc -d -a ${password:+-k "${password}"})
67 | fi
68 | }
69 |
70 | function help() {
71 | local a=(${0//\// })
72 | local bin=${a[${#a[@]}-1]}
73 |
74 | echo 'Usage:'
75 | echo " ${bin} download [ [file]]"
76 | echo ' [--decrypt|-d] [--file|-f ] [--password|-p ] [--trace|-x]'
77 | echo ' [--url|-u ]'
78 | echo
79 | echo " ${bin} upload [ [slug]]"
80 | echo ' [--encrypt|-e] [--file|-f ] [--password|-p ] [--slug|-s ]'
81 | echo ' [--trace|-x]'
82 | echo
83 | echo 'Commands:'
84 | echo ' download Download from transfer.sh to file or piped output'
85 | echo ' upload Upload a file, directory, or piped input to transfer.sh'
86 | echo
87 | echo 'More Information:'
88 | echo ' chat https://rockymadden-slack.herokuapp.com'
89 | echo ' repo https://github.com/rockymadden/transfer-cli'
90 | }
91 |
92 | function upload() {
93 | ! [ -d ${file} ] && ! [ -f "${file}" ] && { echo 'File should exist' ; return 1; }
94 | [ -z "${file}" ] && [ -z "${stdin}" ] && { echo 'File should be provided' ; return 1; }
95 | [ -z "${file}" ] && [ -n "${stdin}" ] && [ -z "${slug}" ] && { echo 'Slug should be provided' ; return 1; }
96 |
97 | local tmpurl=$(mktemp -t transfer.url.XXXXXXXX)
98 | trap "rm -f ${tmpurl}" 0
99 |
100 | if [ -n "${file}" ]; then
101 | if [ -d ${file} ]; then
102 | [ -z "${slug}" ] && slug="$(basename ${file} | sed -e 's/[^a-zA-Z0-9._-]/-/g').tar.gz"
103 |
104 | local tmptar=$(mktemp -t transfer.tar.gz.XXXXXXXX)
105 | trap "rm -f ${tmpurl} ; rm -f ${tmptar}" 0
106 |
107 | (cd $(dirname ${file}); tar -zcf ${tmptar} $(basename ${file}))
108 |
109 | cat "${tmptar}" |
110 | ([ -z "${encrypt}" ] && cat || openssl aes-256-cbc -a -salt ${password:+-k "${password}"}) |
111 | curl --progress-bar --upload-file - "https://transfer.sh/${slug}" > ${tmpurl}
112 | elif [ -f "${file}" ]; then
113 | [ -z "${slug}" ] && slug="$(basename ${file} | sed -e 's/[^a-zA-Z0-9._-]/-/g')"
114 |
115 | cat "${file}" |
116 | ([ -z "${encrypt}" ] && cat || openssl aes-256-cbc -a -salt ${password:+-k "${password}"}) |
117 | curl --progress-bar --upload-file - "https://transfer.sh/${slug}" > ${tmpurl}
118 | fi
119 | elif [ -n "${stdin}" ]; then
120 | echo "${stdin}" |
121 | ([ -z "${encrypt}" ] && cat || openssl aes-256-cbc -a -salt ${password:+-k "${password}"}) |
122 | curl --progress-bar --upload-file - "https://transfer.sh/${slug}" > ${tmpurl}
123 | fi
124 |
125 | cat ${tmpurl}
126 | if type pbcopy &> /dev/null; then cat ${tmpurl} | tr -d '\n' | pbcopy; fi
127 | }
128 |
129 | function version() {
130 | echo 'v0.2.0'
131 | }
132 |
133 | # COMMAND ROUTING #################################################################################
134 | case "${cmd}" in
135 | --help|-h) help ; exit 0 ;;
136 | --version|-v) version ; exit 0 ;;
137 | download|upload) ${cmd} ; exit ${?} ;;
138 | *) help ; exit 1 ;;
139 | esac
140 |
--------------------------------------------------------------------------------