I am trying to upload documents to my Microsoft OneDrive account using python-onedrive. The command I am using is this:

onedrive-cli put Long\ Filename\ 1.jpg
onedrive-cli put Long\ Filename\ 2.jpg

The problem is that there are a lot of these files, and I want to upload all of them (There is no option to upload an entire directory). I have using the asterisk but that doesn't work either:

user@office-debian:~/Desktop/docs$ onedrive-cli put *
usage: onedrive-cli [-h] [-c path] [-p] [-i] [-e enc] [--debug]

onedrive-cli: error: unrecognized arguments: Long Filename 1.jpg Long Filename 2.jpg

I presume this is because the program expects the spaces to be escaped, but the asterisk doesn't expand them that way. I have tried "piping" the arguments to no avail:

user@office-debian:~/Desktop/docs$ ls | onedrive-cli put
usage: onedrive-cli put [-h] [-n] file [folder]
onedrive-cli put: error: too few arguments

Evidently onedrive-cli doesn't recognise STDIN. Are there any other simple options left? I realise I could probably write a script but I was really hoping to avoid that!

The following seems to work, but it's not really what I had in mind:

for files in * ; do
  onedrive-cli put "$files"

If the following doesn't work...

cd ./target_dir
    set -- *
    onedrive-cli put "$@"

Then it's probably because you need a put for every argument in which case this might:

{    printf 'one-drive-cli' 
     printf " put ///%s///" *
} | sed 's|'\''|&"&"&|g;s|///|'\''|g' |
. /dev/stdin 

But if that doesn't work then your for loop probably is the best shell solution because your python script will only support one upload per invocation.

The best way to do it though is to edit the python script to meet your needs.

  • The script doesn't read file names from stdin. Even if it did, you're assuming that it uses ' to delimit file names, which is not necessarily the case, and in any case you'd need to worry about ' in file names (which is supported under Windows). Jun 10 '14 at 1:00
  • @Gilles - what does Windows have to do with it? And I'm not feeding the script any lines from stdin. I think I don't understand what you mean. In any case the OP accepted the question only minutes after I posted it - I must have got something right. And I make no assumptions about the quotes - those hard'quotes are for the shell. True about ' in filenames though. But I was just trying to help out.
    – mikeserv
    Jun 10 '14 at 1:35
  • Oh, right, sorry, I'd misread. . /dev/stdin is a weird way of doing this — | sh would work just as well here. But my point about quoting stands: if a file name contains a ', your command will fail horribly — here, by executing a command chosen by whoever picked the file names. Jun 10 '14 at 1:40
  • @Gilles - again, that's true. Maybe I'll fix that but I was hoping to get some feedback on what the actual deal was by now. In any case your Python bit is the bit - it's what I recommended OP do as well, even if I didn't have the skill to do it on my own - at least not trivially without hours of trial and error.
    – mikeserv
    Jun 10 '14 at 1:43
  • @Gilles - ok, I fixed the quote thing at least.
    – mikeserv
    Jun 10 '14 at 1:50
usage: onedrive-cli put [-h] [-n] file [folder]

This indicates that the subcommand put of the onedrive-cli program must have either one or two non-option arguments. A file is compulsory (the local file name to upload) and a folder is optional (a remote folder to upload to).

The command onedrive-cli put * passes the names of all files in the current directory as arguments. It works no matter what bizarre characters the file names may contain¹. The problem is that the onedrive-cli program doesn't accept multiple files as arguments, unlike many file manipulation commands.

The loop is the right way to do it:

for file in * ; do
  onedrive-cli put "$file"

The loop may be slow if the command has to authenticate to the server anew for every file. There doesn't seem to be a way to do better with the `onedrive-cli- tool as provided. You could write a few lines of Python (warning: completely untested! In particular I don't know how errors will be signaled.)

#!/usr/bin/env python
import sys
from onedrive import api_v5
api = api_v5.PersistentOneDriveAPI.from_conf({})
for f in sys.argv[1:]:

¹ Exception: for historical reasons, * omits files whose name begin with a . (dot files).


It may be easier to just cll it with find.

find ~/Desktop/docs -type f -exec overdrive-cli put {} \;

exec will take each file handle and feed it into the listed command. The {} denotes the file name, and the \; specifies the end of the exec. So you can even use the following if you want to make sure that each file is uploaded only once.

find ~/Desktop/docs -type f -exec overdrive-cli put {}; mv {} ~/Desktop/old-docs \;

The {} may need to be double-quoted to deal with spaces, but it is not likely.


Make a list of file addresses you want to upload.Make sure none of them has and spaces. then write

import os
#files is the list of addresses
for address in files:
    os.system("onedrive-cli put " + address)
  • Python is powerful, but the creation of the files iterable requires somewhat more than the build in magic Python provides. Can you elaborate on how to do that?
    – Anthon
    May 12 '15 at 6:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.