Right so I wanted to automate a process which I have to do quite often for a program that I run quite often and sometimes open up multiple of.
Normally I open up Terminal and type in the following commands in order:
cd ExoClient
mono ExoClient.exe
(email)
(pass)
So I made an executable file for this called login.command on my mac.
I typed in this is order:
cd ExoClient
mono ExoClient.exe
example_email#gmail.com
example_password
So the first two lines work but the last two don't do anything. I thought that this could be because the top 2 commands are actual mac commands and the last two lines are just inputs. But I don't know how to make sure the inputs are inputted.
OR another reason why it might not work could be because I need to delay the inputs. I'd love to know what I can input here to make it wait a second before an input is inputted.
Thanks for reading, would appreciate any help.
I made a similar post on mac rumours.
The solution was to do :
cd ExoClient
mono ExoClient.exe email pass
The first thing to understand about the command-line is that there's a bunch of different things in play.
The first is the commands themselves, these are typically typed in or run from a script.
The second is "standard input" or STDIN, which is where programs take keyboard input. As far as you're concerned there's no difference when using the shell, but to the shell itself there's a huge difference. That program wants input from STDIN. The shell script is being told to run two subsequent commands.
Instead try this:
cd ExoClient
echo "example_email#gmail.com\
example_password" | mono ExoClient.exe
The | character means "send output to" in rough terms, so the output of echo goes through to the mono program. Output, or STDOUT, is another thing the shell wants to deal with.
Or have a secondary file that contains those two lines and give that as "input":
cd ExoClient
mono ExoClient.exe < login.txt
Where login.txt has the two lines and < means "take input from this file".
Related
Say you have a shell command like
cat file1 | ./my_script
Is there any way from inside the 'my_script' command to detect the command run first as the pipe input (in the above example cat file1)?
I've been digging into it and so far I've not found any possibilities.
I've been unable to find any environment variables set in the process space of the second command recording the full command line, the command data the my_script commands sees (via /proc etc) is just _./my_script_ and doesn't include any information about it being run as part of a pipe. Checking the process list from inside the second command even doesn't seem to provide any data since the first process seems to exit before the second starts.
The best information I've been able to find suggests in bash in some cases you can get the exit codes of processes in the pipe via PIPESTATUS, unfortunately nothing similar seems to be present for the name of commands/files in the pipe. My research seems to be saying it's impossible to do in a generic manner (I can't control how people decide to run my_script so I can't force 3rd party pipe replacement tools to be used over build in shell pipes) but it just at the same time doesn't seem like it should be impossible since the shell has the full command line present as the command is run.
(update adding in later information following on from comments below)
I am on Linux.
I've investigated the /proc/$$/fd data and it almost does the job. If the first command doesn't exit for several seconds while piping data to the second command can you read /proc/$$/fd/0 to see the value pipe:[PIPEID] that it symlinks to. That can then be used to search through the rest of the /proc//fd/ data for other running processes to find another process with a pipe open using the same PIPEID which gives you the first process pid.
However in most real world tests I've done of piping you can't trust that the first command will stay running long enough for the second one to have time to locate it's pipe fd in /proc before it exits (which removes the proc data preventing it being read). So if this method will return any information is something I can't rely on.
I want to send commands in the ADB shell itself as if i had done the following in cmd.
>adb shell
shell#:/ <command>
I am using python 3.4 on a windows 7 OS 64bit machine. I can send one-line shell commands simply using subprocess.getoutput such as:
subprocess.getoutput ('adb pull /storage/sdcard0/file.txt')
as long as the adb commands themselves are recognized by ADB specifically, such as pull and push, however there are other commands such as grep that need to be run IN the shell, like above, since they are not recognized by adb. for example, the following line will not work:
subprocess.getoutput ('adb shell ls -l | grep ...')
To enter the commands in the shell I thought I needed some kind of expect library as that is what 'everyone' suggests, however pexpect, wexpect, and winexpect all failed to work. they were written for python 2 and after being ported to python 3 and my going through the .py files by hand, even those tweaked for windows, nothing was working - each of them for different reasons.
how can i send the input i want to the adb shell directly?
If none of the already recommended shortcuts work for you you can still go the 'regular' way using 'subprocess.Popen' for entering commands in the adb shell with Popen:
cmd1 = 'adb shell'
cmd2 = 'ls -l | grep ...'
p = subprocess.Popen(cmd1.split(), stdin=PIPE)
time.sleep(1)
p.stdin.write(cmd2.encode('utf-8'))
p.stdin.write('\n'.encode('utf-8'))
p.stdin.flush()
time.sleep(3)
p.kill()
Some things to remember:
even though you import subprocess you still need to invoke subprocess.Popen
sending cmd1 as a string or as items in a list should work too but '.split()' does the trick and is easier on the eyes
since you only specidfied you want to enter input to the shell you only need stdin=PIPE. stdout would only be necessary if you wanted to receive output from the shell
time.sleep(1) isn't really necessary, however since many complained about input issues being faster or slower in python 2 vs 3 consider maybe using it. 'they' might have been using versions of 'expect' that need the shell's reply first. this code also worked when i tested it with simply swapping out and in the process with time.sleep(0)
stdin.write will return an error if the input is not encoded properly. python's default is unicode. entering by binary did not work for me in my tests like this "b\ls ..." but .encode() worked. dont forget the endline!
if you use .encode() there is a worry that the line might not get sent properly, so to be sure it might be good to include a flush().
time.sleep(3) is completely uneccesary, but if your command takes a long time to execute (eg a regressive search through the entire device piped out to a txt file on the memory card) maybe give it some extra time before killing anyhting.
remember to kill. if you didnt kill it, the pipe may remain open, and even after exiting the test app on the console the next commend still went to the shell even though the prompt appearsed to be my regular cmd prompt.
Amichai, I have to start with pointing out that your own "solution" is pretty awful. And your explanation makes it even worse. Doing all those unnecessary things just because you do not understand how shell (here I mean your PC's OS shell, not adb) command parsing works.
When all you needed was just this one command:
subprocess.check_output(['adb', 'shell', 'ls /storage/sdcard0 | grep ...']).decode('utf-8')
How to tap into the completion of another command programmatically?
Supposing my current directory has files a1, a2, and a3, then how can I make my command invoke the autocompletion of ls a to get back a1 a2 a3?
Is this possible?
Clarification and justification:
I chose ls because people can relate to it. It is a contrived example that is intentionally simple so that people can understand the question without distractions, but unfortunately such examples sometimes take us on tangents. :)
Let me try to exemplify the value of this feature. I have a command called build which, given a directory, can autocomplete to the targets that can be built in that directory. Those targets may not correspond to the files from that directory, and so glob completion (* and other wildcard characters) will not work. The targets might be mined by the build command from a build file that I don't want to be parsing. In other words:
build path/to/dir/TABTAB
Might give:
path/to/dir/a_target
path/to/dir/b_target
Again, a_target and b_target are not files or directories.
build is a pre-existing command, not something I can go ahead and modify to suit my purposes. And the manner in which it comes up with the valid completions is something I certainly don't want to know or reinvent.
Now suppose I have an entire repository of buildable projects, and most of my work and therefore most of my build work happens in only one project. In other words, I always build targets under my/project/directory.
So far so good.
I want to write a wrapper around the build command that doesn't require me to feed it the directory path each time I run it. I want it to know my preferred project directory (or directories, why not) and let me reference the targets without qualifying them:
So under the assumption that I have:
my/project/directory/a_target
my/project/directory/b_target
I want this:
mybuild TABTAB
to give me:
a_target
b_target
Basically I want to decorate and simplify the behavior of build to suit my particular needs.
I will need to write my own completion code for mybuild, but I want it to rely on the completion for build, because I can't ask the developers of build to code a build listtargets command just to make me happy. (Although that would be much more robust.) The build command already has code somewhere that given a prefix can return all the matching targets. It's in the completion for build, and I need to tap into it.
(Of course, when I run mybuild a_target, I will make sure that it knows to run build my/project/directory/a_target. I know how to implement this and it is not in scope for this question.)
I hope this illustrates why I need to tap into the completion of the build command and invoke it as a black box.
This is a bit of an odd thing to do, and the command you need to execute depends on the number of files in the directory - none, one, or more than one. But this command works for the example case:
echo echo a$'\t'$'\t' | bash -i 2>&1 | head -3 | tail -1
The command being autocompleted is
echo a
so send that as a character stream, followed by two tab characters, into an interactive bash shell. bash produces the autocompletion output on stderr, so redirect that to stdout and pipe that through head and tail to select one line of output from the whole. That produces, in this case, the one-line output
a1 a2 a3
But, as others say, just using
echo a*
might be easier!
Bash has something similar to this called globbing.
So for example in your case you could run the command
echo a*
Which would produce:
a1 a2 a3
This is very useful where you have spaces in the names of your files as you can say
for i in a*
do
echo $i
done
And it would work for a1 as well as a 1
Auto-completion is a feature provided by your shell (e.g. bash). The shell will try to offer auto-complete suggestions based on the context of the command you're trying to run and the environment. E.g. it knows that some commands will work on files and can offer some auto-completion based on file paths. But the command itself is not aware on how the arguments it has been run with have been specified, either by the user or with help of auto-completion.
I'm thinking a hypothetical CMDOUTPUT would be useful:
locate -r 'regexp...' # locate finds a file: /myfile.
# Shell puts `/myfile' string into CMDOUTPUT
vim $CMDOUTPUT # No need to run locate again as with: vim `!!`
The locate command above is just an example. I want the output saved for all commands that I run so that if I need it I can access it quickly. (The output should still be printed by the command to stdout.) I don't want to do
CMDOUTPUT="$(...)"
or
command | tee /tmp/cmdoutput
or anything else that I have to do because that's more typing for me at the prompt for everything that I run: I want the shell to do it all in the background. Again, to make it clear: I am casually typing commands away and decide "Oh, I want to use the output of that last command in this command, let me just retrieve it...". Can I tell the shell to store the output somehow so that I can retrieve it.
If there's no option for it, is there some way that I can implement it that is as close to invisible as it can be, meaning exit codes from the command are not lost (...and that's all I can think of, but I'm sure there are other subtleties) etc. I'm primarily thinking of zsh, but answers for any shell would be useful.
I found a solution, not sure if this is exactly what you're looking for. But it should provide a start :)
zsh | tee log >&1
I recently discovered 'comint-show-output' in emacs shell mode, which jumps to the first line of shell output, which I find incredibly handy when looking at shell output that exceeds a screen length. The advantages of this command over scrolling with 'page up' are A) you don't have to scan with your eyes for the first line of the output B) you only have to hit the key combo once (instead of 'page up' a number of times which probably is not known beforehand).
I thought about ending all my commands with '| more' but actually this is not what I want since most of the time, I want to retain all output in the terminal buffer, and I usually want to see the end of the shell output first.
I use OSX. Is there a terminal app (on os x) and shell (on remote linux) combination equivalent (so I can do something similar without using emacs all the time - I know, crazy talk)? I normally use bash, but would be fine with switching shells just for this feature.
The way I do this sort of thing is by sending my output to a file and then watching the file as it is written. You still get the results of the command dumped to terminal history in real time and can still inspect the output's actual contents further after the fact (or in another terminal, etc...)
command > output &
tail -f output
head output
You could always do something in bash like this:
alias foo='!! | more'
which would make foo run the previous command with more. I'm not sure of any way to do exactly what you are suggesting.
If you're expecting a lot of output and don't want to run your command twice, you can use tee(1) to fork the output:
my-command | tee /tmp/my-command.log | less
This will pipe the output to a paginator (less), while simultaneously logging the output to a file (in this case, a file named /tmp/my-command.log). If you need to review the output after you've quit from less, you can just cat the log file instead of re-running the command.