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.
Running a Command with subprocess In the first line, we import the subprocess module, which is part of the Python standard library. We then use the subprocess. run() function to execute the command.
Use the mv command to move files and directories from one directory to another or to rename a file or directory. If you move a file or directory to a new directory without specifying a new name, it retains its original name. Attention: The mv command can overwrite many existing files unless you specify the -i flag.
The subprocess module defines one class, Popen and a few wrapper functions that use that class. The constructor for Popen takes arguments to set up the new process so the parent can communicate with it via pipes. It provides all of the functionality of the other modules and functions it replaces, and more.
Setting the shell argument to a true value causes subprocess to spawn an intermediate shell process, and tell it to run the command. In other words, using an intermediate shell means that variables, glob patterns, and other special shell features in the command string are processed before the command is run.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With