-1

I am trying to move a folder into another folder but am getting Permission Denied error when I try to perform this operation in a Python script vs. the move working successfully when I run it in bash or even in Python interactive mode.

cmd = ['sudo', 'mv', '/path1/dir', '/path2']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != 0:
     print(stderr)    

I also tried adding shell=True.

p = subprocess.Popen(' '.join(cmd), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != 0:
     print(stderr)

In both cases, I am getting the following error:

 "mv: cannot move '/path1/dir' to '/path2/dir': Permission denied\n"

I invoke my script in the following manner:

sudo python script.py

I tried executing each command in shell as well as Python interactive mode and I don't get any errors. Any idea what is going on over here?

Parth Shah
  • 2,060
  • 1
  • 23
  • 34
  • `mv` is a shell command, try executing it through the default shell: `cmd = ['sudo', '-s', 'mv', '/path1/dir', '/path2']` . The question is - since you're already execute your Python script as superuser, why do you resort to subprocess to move your files - just do it directly through Python (check the [`shutil`](https://docs.python.org/3/library/shutil.html) module, for example). – zwer Oct 02 '18 at 08:05
  • Without sudo, it throws the Permission Denied error. When you say default shell, do you mean to not do shell=True? – Parth Shah Oct 02 '18 at 08:09
  • At the moment, it throws Permission Denied error with/without sudo. I thought adding sudo would help. – Parth Shah Oct 02 '18 at 08:12
  • No, just add `-s` to the command list as I've typed in my first comment - that will tell `sudo` to run a shell process as a superuser and then execute your move command in it. But you don't need subprocess at all if you're running your Python script as a _sudoer_ - [`shutil.move()`](https://docs.python.org/3/library/shutil.html#shutil.move) should do just fine. – zwer Oct 02 '18 at 08:15
  • I tried both removing sudo and adding -s after sudo. Neither worked. Is shutil my only option? – Parth Shah Oct 02 '18 at 08:18
  • Your command should work properly even without `-s` if you execute your Python script as a _sudoer_, but `-s` makes it explicit. Are you sure you're not missing something? Also, what's wrong with `shutil.move()`? It practically does the same thing as `mv` without the intermediary shell. – zwer Oct 02 '18 at 09:04

1 Answers1

0

After wasting hours of time debugging as to what was going wrong, I finally figured out what was happening. I was creating /path1 and /path2 using tempfile. Here is a snippet of the code:

class UtilitiesTest(unittest.TestCase):
    @staticmethod
    def createTestFiles():
        dir = tempfile.mkdtemp()
        _, file = tempfile.mkstemp(dir=dir)
        return dir, file

    def test_MoveFileToAnotherLocation(self):
        src_dir, src_file = UtilitiesTest.createTestFiles()
        dest_dir, dest_file = UtilitiesTest.createTestFiles()
        cmd = ['sudo', 'mv', src_dir, dest_dir]
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = p.communicate()
        if p.returncode != 0:
             print(stderr)

Like zwer said in the comments, if I am running this script using sudo, I don't need to add sudo in my mv command. Because I kept getting permission denied errors, I kept thinking that sudo would fix my problem. The actual issue over here was when tempfile.mkstemp() is called, it returns an open file descriptor along with the file path. I didn't pay much attention to the first argument, so when I modified my createTestFiles() to below, everything started working.

    @staticmethod
    def createTestFiles():
        dir = tempfile.mkdtemp()
        fd, file = tempfile.mkstemp(dir=dir)
        os.close(fd)
        return dir, file
Parth Shah
  • 2,060
  • 1
  • 23
  • 34