How to use the mv command in Python with subproces

2019-04-25 09:18发布

I have a lot of files in /home/somedir/subdir/ and I'm trying to move them all up to /home/somedir programmatically.

right now I have this:

subprocess.call(["mv", "/home/somedir/subdir/*", "somedir/"])

but it's giving me this error:

mv: cannot stat `/home/somedir/subdir/*': No such file or directory

I know that it does exist because when I type the mv command by hand using the exact same command as the script uses it works perfectly.

3条回答
倾城 Initia
2楼-- · 2019-04-25 09:33

You are using shell globbing *, and expecting the mv command to know what it means. You can get the same error from a command shell this way:

$ mv 'somedir/subdir/*' ...

Notice the quotes. The shell usually does glob-matching on * for you, but commands don't do that on their command lines; not even a shell does. There is a C library function called fnmatch that does shell-style globbing for you, which every programming language more or less copies. It might even have the same name in Python. Or it might have the word "glob" in it; I don't remember.

查看更多
Anthone
3楼-- · 2019-04-25 09:36

if you call subprocess that way:

subprocess.call(["mv", "/home/somedir/subdir/*", "somedir/"])

you're actually giving the argument /home/somedir/subdir/* to the mv command, with an actual * file. i.e. you're actually trying to move the * file.

subprocess.call("mv /home/somedir/subdir/* somedir/", shell=True)

it will use the shell that will expand the first argument.

Nota Bene: when using the shell=True argument you need to change your argument list into a string that will be given to the shell.

Hint: You can also use the os.rename() or shutil.move() functions, along with os.path.walk() or os.listdir() to move the files to destination in a more pythonic way.

查看更多
Bombasti
4楼-- · 2019-04-25 09:45

You can solve this by adding the parameter shell=True, to take into account wildcards in your case (and so write the command directly, without any list):

subprocess.call("mv /home/somedir/subdir/* somedir/", shell=True)

Without it, the argument is directly given to the mv command with the asterisk. It's the shell job to return every files which match the pattern in general.

查看更多
登录 后发表回答