I am trying to find the path to a file named 'config.txt' from a usb flash drive plugged into a raspberry pi. The physical drive that is used may not always be the same, so the path may not always be the same. So I use
'find /media/pi/*/config.txt'
to locate the path in the terminal and works just fine.
Now I go to use check_output and get a giant string of paths.
from subprocess import check_output
cmd = ['find', '/media/pi/*/config.txt']
out = check_output(cmd,shell=True)
I set the shell as True to allow wild cards, according to https://docs.python.org/2/library/subprocess.html
Results for out are:
'.\n./.Xauthority\n./.xsession-errors\n./Public\n./.dmrc\n./Downloads\n./test.sh\n./.idlerc\n./.idlerc/recent-files.lst\n./.idlerc/breakpoints.lst\n./.asoundrc\n./.bash_logout\n./.profile\n./Templates\n./Music\n./.bash_history\n./Videos\n./.local\n./.local/share\n./.local/share/gvfs-metadata\n./.local/share/gvfs-metadata/home\n./.local/share/gvfs-metadata/home-d6050e94.log\n./.local/share/applications\n./.local/share/recently-used.xbel\n./.local/share/Trash\n.....
And it continues to go on for awhile.
I tried looking at several other similar questions including the link below, but no luck.
Store output of subprocess.Popen call in a string
You would need to pass a single string exactly as you would from your shell if you want to use a wildcard:
from subprocess import check_output
cmd = 'find /media/pi/*/config.txt'
out = check_output(cmd,shell=True)
You don't actually need subprocess at all, glob will do what you want:
from glob import glob
files = glob('/media/pi/*/config.txt')
Since you are using the shell=True you can use the following:
from subprocess import check_output
cmd = 'cd /media/pi && find . -iname config.txt'
out = check_output(cmd, shell=True)
Try to avoid use of wildcards if possible, and just change your current working directory before searching for your target file.
Related
I have a command which I use for deployment from windows command line. Now I need to run the same from an external python3.4 script.
The command is C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild "D:\WebService\WebService.sln" /p:DeployOnBuild=true /p:PublishProfile="D:\WebService\Properties\PublishProfiles\MyDeployment.pubxml" /p:AllowUntrustedCertificate=true /p:UserName=name /p:Password=PASSWORD.
How can I achieve this. I tried subprocess . But it's not working.Please help me out.
Your problems appear to be the \ and " characters, so use raw strings. Also, it is safer to use a list:
proc = subprocess.Popen(
[r"C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild",
r"D:\WebService\WebService.sln",
r"/p:DeployOnBuild=true",
r"/p:PublishProfile=D:\WebService\Properties\PublishProfiles\MyDeployment.pubxml",
r"/p:AllowUntrustedCertificate=true",
r"/p:UserName=name",
r"/p:Password=PASSWORD"])
proc.wait()
Strictly speaking you don't need raw strings for all those parameters, but it is safer to do so with Windows paths. You only need the internal double quotes if you have embedded whitespace (as the first parameter). Here we are not using a shell, set shell=True as a parameter if you need one. A reason to use a shell on Windows is for filename association, but you don't appear to be using that here.
Can you post some code with what you have tried so far?
The subprocess module should be able to handle that, with something like
theproc = subprocess.Popen(["COMMAND HERE"])
theproc.communicate()
or you could try with the shell flag
theproc = subprocess.Popen(["COMMAND HERE"], shell=True)
I am attempting to write a script that utilises sys.argv to wrap the scp command. The idea, is that you will be able to run: pyscp folder/* host but if I run this script with those arguments:
import sys
for arg in sys.argv:
print arg
I get a list of all the folders inside folder:
pyscp.py
folder/0
folder/1
folder/2
folder/3
folder/4
folder/5
folder/67
folder/8
folder/9
host
Assuming a UNIXoid operating system: The shell is expanding the * into the matching files. Try to call your script like
pyscp "folder/*" host
The quotes keep the shell from interpreting the * character.
If you do not escape the asterisk, the shell is performing filename expansion for you. The pattern including the asterisk becomes replaced with an alphabetically sorted list of file names matching the pattern before your Python program becomes executed. You can prevent the shell from performing filename expansion using e.g. single quotes, i.e.
pyscp 'folder/*' hostname
You can then do this yourself within Python using the glob module and control things the way you want it.
The shell is expanding the file list for you. You can leverage this by allowing multiple parameters in the command.
import sys
files = sys.argv[1:-1]
host = sys.argv[-1]
Now you have a more flexible program that lets caller jump through whatever hoops he wants for the transfer, like maybe all text files in folder1 plus anything that's changed in the last day in folder2 (on a linux machine):
pyscp folder1/*.txt `find -mtime -1` example.com
In the Linux kernel, I can send a file to the printer using the following command
cat file.txt > /dev/usb/lp0
From what I understand, this redirects the contents in file.txt into the printing location. I tried using the following command
>>os.system('cat file.txt > /dev/usb/lp0')
I thought this command would achieve the same thing, but it gave me a "Permission Denied" error. In the command line, I would run the following command prior to concatenating.
sudo chown root:lpadmin /dev/usb/lp0
Is there a better way to do this?
While there's no reason your code shouldn't work, this probably isn't the way you want to do this. If you just want to run shell commands, bash is much better than python. On the other hand, if you want to use Python, there are better ways to copy files than shell redirection.
The simplest way to copy one file to another is to use shutil:
shutil.copyfile('file.txt', '/dev/usb/lp0')
(Of course if you have permissions problems that prevent redirect from working, you'll have the same permissions problems with copying.)
You want a program that reads input from the keyboard, and when it gets a certain input, it prints a certain file. That's easy:
import shutil
while True:
line = raw_input() # or just input() if you're on Python 3.x
if line == 'certain input':
shutil.copyfile('file.txt', '/dev/usb/lp0')
Obviously a real program will be a bit more complex—it'll do different things with different commands, and maybe take arguments that tell it which file to print, and so on. If you want to go that way, the cmd module is a great help.
Remember, in UNIX - everything is a file. Even devices.
So, you can just use basic (or anything else, e.g. shutil.copyfile) files methods (http://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files).
In your case code may (just a way) be like that:
# Read file.txt
with open('file.txt', 'r') as content_file:
content = content_file.read()
with open('/dev/usb/lp0', 'w') as target_device:
target_device.write(content)
P. S. Please, don't use system() call (or similar) to solve your issue.
under windows OS there is no cat command you should usetype instead of cat under windows
(**if you want to run cat command under windows please look at: https://stackoverflow.com/a/71998867/2723298 )
import os
os.system('type a.txt > copy.txt')
..or if your OS is linux and cat command didn't work anyway here are other methods to copy file..
with grep:
import os
os.system('grep "" a.txt > b.txt')
*' ' are important!
copy file with sed:
os.system('sed "" a.txt > sed.txt')
copy file with awk:
os.system('awk "{print $0}" a.txt > awk.txt')
I am having a problem using my command/commands with one instance of os.system.
Unfortunately I have to use os.system as I have no control over this, as I send the string to the os.system method. I know I should really use subprocess module for my case, but that ain't an option.
So here is what I am trying to do.
I have a string like below:
cmd = "export BASE_PATH=`pwd`; export fileList=`python OutputString.py`; ./myscript --files ${fileList}; cp outputfile $BASE_PATH/.;"
This command then gets sent to the os.system module like so
os.system(cmd)
unfortunately when I consult my log file I get something that looks like this
os.system(r"""export BASE_PATH=/tmp/bla/bla; export fileList=; ./myscript --files ; cp outputfile /.;""")
As you can see BASE_PATH seems to be working but then when I call it with the cp outputfile /.
I get a empty string
Also with my fileList I get a empty string as fileList=python OutputString.py should print out a file list to this variable.
My thoughts:
Are these bugs due to a new process for each command? Hence I loose the variable in BASE_PATH in the next command.
Also for I not sure why fileList is empty.
Is there a solution to my above problem using os.system and my command string?
Please Note I have to use os.system module. This is out of my control.
I am trying to do $ mv <file> .. in a python script using subprocess.call(). I am able to do this on 'normal' filenames, but on certain filenames it does not work. I do not have control of the filenames that are given to the script. Here is an example:
M filename is "ITunes ES Film Metadata_10_LaunchTitles(4th Batch)_08_20_2010.XLS"
When I try and do the command directly into the python prompt and drag the file into it, this is what I get:
>>> /Users/David/Desktop/itunes_finalize/TheInventionOfLying_CSP/
ITunes\ ES\ Film\ Metadata_10_LaunchTitles\(4th\ Batch\)_08_20_2010.XLS
No such file or directory
How would I go about moving this file in a python script?
Update:
Thanks for the answers, this is how I ended up doing it:
for file in glob.glob(os.path.join(dir, '*.[xX][lL][sS]')):
shutil.move(file, os.path.join(os.path.dirname(file), os.path.pardir))
subprocess is not the best way to go here. For example, what if you're on an operating system that isn't POSIX compliant?
Check out the shutil module.
>>> import shutil
>>> shutil.move(src, dest)
If finding the actual string for the filename is hard you can use glob.glob to pattern match what you want. For example, if you're running the script/prompt from the directory with the .XLS file in question you could do the following.
>>> import glob
>>> glob.glob('*ITunes*.XLS')
You'll get a list back with all the file strings that fit that pattern.
Rather than using subprocess and spawning a new process, use shutil.move() to just do it in Python. That way, the names won't be reinterpreted and there will be little chance for error.
Spaces, parens, etc. are the shell's problem. They don't require escaping in Python provided you don't pass them to a shell.
open('*WOW!* Rock&Roll(uptempo).mp3')