From 4e55437411d16a6602d5964fd419c788ffb1a26b Mon Sep 17 00:00:00 2001 From: Henry Fredrick Schreiner Date: Thu, 25 May 2017 15:35:29 -0400 Subject: [PATCH] Escape filename spaces on remotes, fixes #322 --- CHANGELOG.rst | 5 +++++ plumbum/machines/remote.py | 5 ++++- tests/file with space.txt | 0 tests/test_local.py | 8 ++++++++ tests/test_remote.py | 9 +++++++++ 5 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 tests/file with space.txt diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a2f1d9cad..0f8deeda1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,8 @@ +1.6.4 (in progress) +------------------- + +* Fixes for globbing with spaces in filename on a remote server (`#322 `_) + 1.6.3 ----- * Python 3.6 is now supported, critical bug fixed (`#302 `_) diff --git a/plumbum/machines/remote.py b/plumbum/machines/remote.py index 6c4387cc3..23d597627 100644 --- a/plumbum/machines/remote.py +++ b/plumbum/machines/remote.py @@ -321,7 +321,10 @@ def _path_listdir(self, fn): files.remove("..") return files def _path_glob(self, fn, pattern): - matches = self._session.run("for fn in %s/%s; do echo $fn; done" % (fn, pattern))[1].splitlines() + # shquote does not work here due to the way bash loops use space as a seperator + pattern = pattern.replace(" ", r"\ ") + fn = fn.replace(" ", r"\ ") + matches = self._session.run(r'for fn in {0}/{1}; do echo $fn; done'.format(fn,pattern))[1].splitlines() if len(matches) == 1 and not self._path_stat(matches[0]): return [] # pattern expansion failed return matches diff --git a/tests/file with space.txt b/tests/file with space.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_local.py b/tests/test_local.py index 178beb0bf..fa400dc1b 100644 --- a/tests/test_local.py +++ b/tests/test_local.py @@ -318,6 +318,14 @@ def test_path(self): found = True assert found + @skip_on_windows + def test_glob_spaces(self): + fileloc = local.cwd / 'file with space.txt' + assert fileloc.exists() + + assert local.cwd // "*space.txt" + assert local.cwd // "file with*" + @skip_on_windows def test_env(self): assert "PATH" in local.env diff --git a/tests/test_remote.py b/tests/test_remote.py index 95b2d74cb..8a3b50b95 100644 --- a/tests/test_remote.py +++ b/tests/test_remote.py @@ -158,6 +158,15 @@ def test_glob(self): assert "test_remote.py" in filenames assert "slow_process.bash" in filenames + def test_glob_spaces(self): + with self._connect() as rem: + with rem.cwd(os.path.dirname(os.path.abspath(__file__))): + filenames = [f.name for f in rem.cwd // ("*space.txt")] + assert "file with space.txt" in filenames + + filenames = [f.name for f in rem.cwd // ("*with space.txt")] + assert "file with space.txt" in filenames + @pytest.mark.usefixtures("testdir") def test_download_upload(self): with self._connect() as rem: