0

I have the following program

import os
import sys
import subprocess
from pathlib import Path

program = subprocess.check_output("which gphotos-sync", shell=True).decode().strip()

home = Path(os.path.expanduser("~")) / "photos"

args = [
  "--ntfs",
  "--retry-download",
  "--skip-albums",
  "--photos-path ".",
  "--log-level", "DEBUG",
]

env = os.environ.copy()
env["LC_ALL"] = "en_US.UTF-8"

for p in home.glob("*/*"):
  print([program, *args, str(p.relative_to(home))])
  subprocess.run([program, *args, str(p.relative_to(home))], cwd=home, shell=True, env=env, stdout=sys.stdout, stderr=subprocess.STDOUT)

Which prints

['/home/ubuntu/.local/bin/gphotos-sync', '--ntfs', '--retry-download', '--skip-albums', '--photos-path .', '--log-level DEBUG', 'rodrigo/0']
usage: gphotos-sync [-h] [--album ALBUM] [--log-level LOG_LEVEL] [--logfile LOGFILE] [--compare-folder COMPARE_FOLDER] [--favourites-only] [--flush-index] [--rescan] [--retry-download]
                    [--skip-video] [--skip-shared-albums] [--album-date-by-first-photo] [--start-date START_DATE] [--end-date END_DATE] [--db-path DB_PATH] [--albums-path ALBUMS_PATH]
                    [--photos-path PHOTOS_PATH] [--use-flat-path] [--omit-album-date] [--new-token] [--index-only] [--skip-index] [--do-delete] [--skip-files] [--skip-albums] [--use-hardlinks]
                    [--no-album-index] [--case-insensitive-fs] [--max-retries MAX_RETRIES] [--max-threads MAX_THREADS] [--secret SECRET] [--archived] [--progress] [--max-filename MAX_FILENAME]
                    [--ntfs]
                    root_folder

As you can see, gphotos-sync requires the root_folder (the last argument). But if I run the printed command line manually, the program works fine

/home/ubuntu/.local/bin/gphotos-sync --ntfs --retry-download --skip-albums --photos-path . --log-level DEBUG rodrigo/0

Am I missing something?

https://i.imgur.com/wkfVu3z.png

Rodrigo
  • 135
  • 4
  • 45
  • 107
  • 1
    `"--photos-path ".",` is unquestionably wrong. Whether or not changing it to `"--photos-path", "."` is the *only* change you need, there is no possibility that the code would work correctly without it. – Charles Duffy Dec 29 '20 at 18:46
  • 1
    Beyond that: What's with the `shell=True`? That makes only the first argument be treated as code at all; the subsequent arguments are arguments _to that code_, but since the code `/home/ubuntu/.local/bin/gphotos-sync` doesn't _look_ at what its arguments are, that means all other arguments are ignored. – Charles Duffy Dec 29 '20 at 18:48
  • 1
    Beyond that: Don't use `which` to cache PATH lookups. It's bad practice in shell too (where it's much slower than the shell's built-in PATH lookup caching), and it's just as bad in Python. – Charles Duffy Dec 29 '20 at 18:50
  • @CharlesDuffy so I don't need the `shell=True` in my case? I can invoke `gphotos-sync` direct on `process.run`? I'll give I try, thanks for the feedback. – Rodrigo Dec 29 '20 at 19:00
  • 1
    If you wanted to make it work with `shell=True`, you'd need to make it something like `['gphotos-sync "$@"', 'sh', *args, str(p.relative_to(home))]` (first list element is a shell script, second list element is `$0` to that shell script, third and onward are `$1`, `$2` etc., so `"$@"` expands to the entire set of them), but just turning off `shell=True` is definitely the better approach. – Charles Duffy Dec 29 '20 at 19:05

1 Answers1

0

When an option takes a parameter, they either need to be separate arguments or you have to use --option=parameter syntax. You can't put them in the same argument separated by space.

So it should be:

args = [
  "--ntfs",
  "--retry-download",
  "--skip-albums",
  "--photos-path", ".",
  "--log-level", "DEBUG",
]
Barmar
  • 741,623
  • 53
  • 500
  • 612