Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example Zsh/Bash function for transfer.sh homepage #475

Closed
keks24 opened this issue Mar 24, 2022 · 13 comments · Fixed by #478
Closed

Example Zsh/Bash function for transfer.sh homepage #475

keks24 opened this issue Mar 24, 2022 · 13 comments · Fixed by #478

Comments

@keks24
Copy link
Contributor

keks24 commented Mar 24, 2022

Hello,

I just want to share this. If you consider my function as an worthy example for the homepage, go for it!:

transfer()
{
    local file="${1}"
    local filename="${file##*/}"
    # show delete link from the response header after upload. the command "sed" is necessary to clean up the output, "gsub()" in "awk" does not work.
    curl --request PUT --progress-bar --dump-header - --upload-file "${file}" "https://transfer.sh/${filename}" | sed "s/#//g" | awk '/x-url-delete/ { print "Delete command: curl --request DELETE " $2 } END{ print "Download link: " $1 }'
}

Example outputs:

$ transfer image.img
######################################################################################################################################################################################################################################## 100.0%
Delete command: curl --request DELETE https://transfer.sh/Ge9cuW/image.img/<some_delete_token>
Download link: https://transfer.sh/Ge9cuW/image.img
$ transfer /tmp/tmp.LkwBEu5r64/image2.img
######################################################################################################################################################################################################################################## 100.0%
Delete command: curl --request DELETE https://transfer.sh/oeopqy/image2.img/<some_delete_token>
Download link: https://transfer.sh/oeopqy/image2.img

-Ramon

@aspacca
Copy link
Collaborator

aspacca commented Apr 3, 2022

nice @keks24 , thanks for sharing

I will add to README.md for the moment, since the frontend is already cluttered with examples unluckily :(

if you are able to write a cross-shell (bash/zsh at least) version of your function, including echoing delete command (that's really great!) we could promote it to frontend.

please let me know what do you think

@gingerbeardman
Copy link

Yeah, delete command is not shown when using zsh

@keks24
Copy link
Contributor Author

keks24 commented Apr 3, 2022

I just tested this on my end and it works for zsh and bash.

What output do you get, if you upload a small file via curl like the following?:

$ echo "some_content" > "deleteme"
$ curl --request PUT --progress-bar --dump-header - --upload-file "deleteme" "https://transfer.sh/deleteme"

curl returns me this:

HTTP/2 200
server: nginx/1.14.2
date: Sun, 03 Apr 2022 12:33:31 GMT
content-type: text/plain
content-length: 35
retry-after: Sun, 03 Apr 2022 14:33:31 GMT
x-made-with: <3 by DutchCoders
x-ratelimit-key: <censored>
x-ratelimit-limit: 10
x-ratelimit-rate: 600
x-ratelimit-remaining: 9
x-ratelimit-reset: 1648989211
x-served-by: Proudly served by DutchCoders
x-url-delete: https://transfer.sh/cmlWRe/deleteme/s7ljRXJuPtdT
strict-transport-security: max-age=63072000

https://transfer.sh/cmlWRe/deleteme%

Maybe the key x-url-delete is written differently and not matched by gawk.


These are the package versions I am using and an upload test, which I did in bash:

$ zsh --version
zsh 5.8.1 (x86_64-pc-linux-gnu)
$ curl --version
curl 7.79.1 (x86_64-pc-linux-gnu) libcurl/7.79.1 OpenSSL/1.1.1n zlib/1.2.11 zstd/1.5.2 nghttp2/1.45.1
Release-Date: 2021-09-22
Protocols: dict file ftp ftps http https imap imaps mqtt pop3 pop3s rtsp smtp smtps tftp
Features: HTTP2 HTTPS-proxy IPv6 Largefile libz NTLM SSL TLS-SRP UnixSockets zstd
$ ls -l $(command -v awk)
lrwxrwxrwx 1 root root 4 Nov 13  2018 /usr/bin/awk -> gawk
$ gawk --version
GNU Awk 5.1.1, API: 3.1
Copyright (C) 1989, 1991-2021 Free Software Foundation.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
$ bash --version
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

I refactored the function to intercept errors, but the origin function above works as well for zsh and bash:
~/.bashrc

[...]
# Put your fun stuff here.
## upload files to "transfer.sh"
transfer()
{
    local file="${1}"
    if [[ ! -f "${file}" ]]
    then
        echo -e "\e[01;31mCould not find file: '${file}'.\e[0m" >&2
        return 1
    else
        local filename="${file##*/}"
        # show delete link from the response header after upload. the command "sed" is necessary to clean up the output, "gsub()" in "awk" does not work.
        curl --request PUT --progress-bar --dump-header - --upload-file "${file}" "https://transfer.sh/${filename}" \
            | sed "s/#//g" \
            | awk '/x-url-delete/ { print "Delete command: curl --request DELETE " $2 } END{ print "Download link: " $1 }'
    fi
}
$ bash
$ cd $(mktemp --directory)
$ dd if=/dev/zero of=image.img bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00520936 s, 2.0 GB/s
$ ls -lh
total 10M
-rw-r--r-- 1 ramon ramon 10M Apr  3 14:30 image.img
$ transfer image.img
######################################################################################################################################################################################################################################## 100.0%
Delete command: curl --request DELETE https://transfer.sh/QW3WDd/image.img/euCXr1ibfNK9
Download link: https://transfer.sh/QW3WDd/image.img
$ curl --request DELETE https://transfer.sh/QW3WDd/image.img/euCXr1ibfNK9

@keks24
Copy link
Contributor Author

keks24 commented Apr 3, 2022

I found the issue!

It seems, that x-url-delete is written differently in some versions of curl as seen in the README.md file.

Since there are different versions of awk like gawk, mawk and so on, I am going to match x-url-delete without case sensitivity; using the variable IGNORECASE only works for gawk and is not sufficient.

This function should work now:

## upload files to "transfer.sh"
transfer()
{
    local file="${1}"
    if [[ ! -f "${file}" ]]
    then
        echo -e "\e[01;31mCould not find file: '${file}'.\e[0m" >&2
        return 1
    else
        local filename="${file##*/}"
        # show delete link from the response header after upload. the command "sed" is necessary to clean up the output, "gsub()" in "awk" does not work.
        curl --request PUT --progress-bar --dump-header - --upload-file "${file}" "https://transfer.sh/${filename}" \
            | sed "s/#//g" \
            | awk 'tolower($0) ~ /x-url-delete/ { print "Delete command: curl --request DELETE " $2 } END{ print "Download link: " $1 }'
    fi
}

@aspacca
Copy link
Collaborator

aspacca commented Apr 3, 2022

$ /bin/zsh
 ~ % transfer()
{
    local file="${1}"
    if [[ ! -f "${file}" ]]
    then
        echo -e "\e[01;31mCould not find file: '${file}'.\e[0m" >&2
        return 1
    else
        local filename="${file##*/}"
        # show delete link from the response header after upload. the command "sed" is necessary to clean up the output, "gsub()" in "awk" does not work.
        curl --request PUT --progress-bar --dump-header - --upload-file "${file}" "https://transfer.sh/${filename}" \
            | sed "s/#//g" \
            | awk '/x-url-delete/ { print "Delete command: curl --request DELETE " $2 } END{ print "Download link: " $1 }'
    fi
}
 ~ % cd $(mktemp -d)
tmp.xn12kP8i % dd if=/dev/zero of=image.img bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes transferred in 0.002949 secs (3555700237 bytes/sec)
tmp.xn12kP8i % transfer image.img
transfer:9: command not found: #
################################################################################################################# 100,0%
Delete command: curl --request DELETE https://transfer.sh/nWrgYc/image.img/rPwidfFnwsFb
Download link: https://transfer.sh/nWrgYc/image.img
tmp.xn12kP8i %

not sure about that transfer:9: command not found: #

@keks24
Copy link
Contributor Author

keks24 commented Apr 3, 2022

I think, that has something to do with --progress-bar, which is not perfectly removed by sed.

Does this one with --silent and --show-error without sed work for you?:

$ curl --request PUT --silent --show-error --dump-header - --upload-file "image.img" "https://transfer.sh/image.img" | awk 'tolower($0) ~ /x-url-delete/ { print "Delete command: curl --request DELETE " $2 } END{ print "Download link: " $1 }'

Leaving out the parameter --silent messes up the output for some reason:

$ curl --request PUT --dump-header - --upload-file "image.img" "https://transfer.sh/image.img" | awk 'tolower($0) ~ /x-url-delete/ { print "Delete command: curl --request DELETE " $2 } END{ print "Download link: " $1 }'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 10.0M  100    36  100 10.0M      6  1726k  0:00:06  0:00:05  0Delete command: curl --request DELETE https://transfer.sh/jwnvkk/image.img/mJTdLmALDh7N
100 10.0M  100    36  100 10.0M      6  1726k  0:00:06  0:00:05  0:00:01  887k
Download link: https://transfer.sh/jwnvkk/image.img

@keks24

This comment was marked as outdated.

@keks24
Copy link
Contributor Author

keks24 commented Apr 4, 2022

I could not help myself, but to improve the function once again. It is slowly growing, where I almost got to the point to create a separate repository for it, but I will keep it like this for now.

I consider this the final version now.

It can now upload multiple files, shows the size of each file in Kibibyte and prompts before uploading:

$ transfer --help
transfer - Upload arbitrary files to "transfer.sh".

Usage: transfer [options] [<file>]...

OPTIONS:
  -h, --help
      show this message

EXAMPLES:
  Upload a single file from the current working directory:
      transfer "image.img"

  Upload multiple files from the current working directory:
      transfer "image.img" "image2.img"

  Upload a file from a different directory:
      transfer "/tmp/some_file"

  Upload all files from the current working directory. Be aware of the webserver's rate limiting!:
      transfer *

  Upload a single file from the current working directory and filter out the delete command:
      transfer "image.img" | awk --field-separator="Delete command:" '/Delete command:/ { print $2 }'

  Show help text from "transfer.sh":
      curl --request GET "https://transfer.sh"
## upload files to "transfer.sh"
transfer()
{
    local upload_files
    local curl_output
    local awk_output
    local filename
    local file
    declare -a file_array
    file_array=("${@}")

    if [[ "${file_array[@]}" == "" || "${1}" == "--help" || "${1}" == "-h" ]]
    then
        echo "${0} - Upload arbitrary files to \"transfer.sh\"."
        echo ""
        echo "Usage: ${0} [options] [<file>]..."
        echo ""
        echo "OPTIONS:"
        echo "  -h, --help"
        echo "      show this message"
        echo ""
        echo "EXAMPLES:"
        echo "  Upload a single file from the current working directory:"
        echo "      ${0} \"image.img\""
        echo ""
        echo "  Upload multiple files from the current working directory:"
        echo "      ${0} \"image.img\" \"image2.img\""
        echo ""
        echo "  Upload a file from a different directory:"
        echo "      ${0} \"/tmp/some_file\""
        echo ""
        echo "  Upload all files from the current working directory. Be aware of the webserver's rate limiting!:"
        echo "      ${0} *"
        echo ""
        echo "  Upload a single file from the current working directory and filter out the delete token and download link:"
        echo "      ${0} \"image.img\" | awk --field-separator=\": \" '/Delete token:/ { print \$2 } /Download link:/ { print \$2 }'"
        echo ""
        echo "  Show help text from \"transfer.sh\":"
        echo "      curl --request GET \"https://transfer.sh\""
        return 0
    else
        for file in "${file_array[@]}"
        do
            if [[ ! -f "${file}" ]]
            then
                echo -e "\e[01;31m'${file}' could not be found or is not a file.\e[0m" >&2
                return 1
            fi
        done
    fi
    unset file

    du --total --block-size="K" --dereference "${file_array[@]}" >&2
    # be compatible with "bash"
    if [[ "${ZSH_NAME}" == "zsh" ]]
    then
        read $'upload_files?\e[01;31mDo you really want to upload the above files ('"${#file_array[@]}"$') to "transfer.sh"? (Y/n): \e[0m'
    elif [[ "${BASH}" == *"bash"* ]]
    then
        read -p $'\e[01;31mDo you really want to upload the above files ('"${#file_array[@]}"$') to "transfer.sh"? (Y/n): \e[0m' upload_files
    fi

    case "${upload_files:-y}" in
        "y"|"Y")
            # for the sake of the progress bar, execute "curl" for each file.
            # the parameters "--include" and "--form" will suppress the progress bar.
            for file in "${file_array[@]}"
            do
                filename="${file##*/}"
                # show delete link and filter out the delete token from the response header after upload.
                # it is important to save "curl's" "stdout" via a subshell to a variable or redirect it to another command,
                # which just redirects to "stdout" in order to have a sane output afterwards.
                # the progress bar is redirected to "stderr" and is only displayed,
                # if "stdout" is redirected to something; e.g. ">/dev/null", "tee /dev/null" or "| <some_command>".
                # the response header is redirected to "stdout", so redirecting "stdout" to "/dev/null" does not make any sense.
                # redirecting "curl's" "stderr" to "stdout" ("2>&1") will suppress the progress bar.
                curl_output=$(curl --request PUT --progress-bar --dump-header - --upload-file "${file}" "https://transfer.sh/${filename}")
                awk_output=$(awk 'tolower($1) ~ /x-url-delete/ \
                    { gsub("\r", "", $0); print "Delete command: curl --request DELETE " "\""$2"\""; \
                      gsub(".*/", "", $2); print "Delete token: " $2 } \
                      END{ print "Download link: " $0 }' <<< "${curl_output}")

                # return the results via "stdout", "awk" does not do this for some reason.
                echo -e "${awk_output}\n"

                # avoid rate limiting as much as possible; nginx: too many requests.
                if (( ${#file_array[@]} > 4 ))
                then
                    sleep 5
                fi
            done
            ;;

        "n"|"N")
            return 1
            ;;

        *)
            echo -e "\e[01;31mWrong input: '${upload_files}'.\e[0m" >&2
            return 1
    esac
}
$ ls -lh
total 20M
-rw-r--r-- 1 ramon ramon 10M Apr  4 21:08 image.img
-rw-r--r-- 1 ramon ramon 10M Apr  4 21:08 image2.img
$ transfer image*
10240K  image2.img
10240K  image.img
20480K  total
Do you really want to upload the above files (2) to "transfer.sh"? (Y/n):
######################################################################################################################################################################################################################################## 100.0%
Delete command: curl --request DELETE "https://transfer.sh/wJw9pz/image2.img/mSctGx7pYCId"
Delete token: mSctGx7pYCId
Download link: https://transfer.sh/wJw9pz/image2.img

######################################################################################################################################################################################################################################## 100.0%
Delete command: curl --request DELETE "https://transfer.sh/ljJc5I/image.img/nw7qaoiKUwCU"
Delete token: nw7qaoiKUwCU
Download link: https://transfer.sh/ljJc5I/image.img

$ transfer "image.img" | awk --field-separator=": " '/Delete token:/ { print $2 } /Download link:/ { print $2 }'
10240K  image.img
10240K  total
Do you really want to upload the above files (1) to "transfer.sh"? (Y/n):
######################################################################################################################################################################################################################################## 100.0%
tauN5dE3fWJe
https://transfer.sh/MYkuqn/image.img

keks24/dotfiles@62ed27d...4c0006f

@keks24 keks24 changed the title Example Zsh function for transfer.sh homepage Example Zsh/Bash function for transfer.sh homepage Apr 4, 2022
@aspacca
Copy link
Collaborator

aspacca commented Apr 5, 2022

@keks24 thank you very much for you effort!

I will try to add this to the frontend in the weekend

@keks24
Copy link
Contributor Author

keks24 commented Apr 6, 2022

My pleasure! 😃

If it is too big for the README.md, you may want to put it into an expandable detail section:

Some details

$ some_command

@aspacca
Copy link
Collaborator

aspacca commented Apr 20, 2022

@keks24 , thank you very much

if you have time and you can open a PR to directly update the README.md it would be awesome

I'm a little busy this days and I'm not sure when I'll be able to do on my own 🙏

@keks24
Copy link
Contributor Author

keks24 commented Apr 20, 2022

@aspacca

I already did that in #478, which also got merged by @stefanbenten. :)

@aspacca
Copy link
Collaborator

aspacca commented Apr 20, 2022

lol, thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants