Need to answer half questions automatically on script - shell

Is it possible to answer first few or a part of questions automatically and rest manually?
I am connecting to a VPN daily which gives first prompt to say "yes" or "no", second one to choose a group and third one to input username. Upto three questions, answers will be same. Fourth prompt is a physical RSA token input and fifth one is a password.
When I script it with an input file for first three questions (eg; ./script < inputfile), the connection exits as below.
GROUP: [xxxx|abcdgroup01|sssgroup01|sssssgroup01z]:Please enter your username and password.
Username:Password:
fgets (stdin): Inappropriate ioctl for device
This is happening because the script is not getting the fourth answer from the input file.
Out of five inputs, four are static ones and the fourth one is a dynamic one.
How do I manage to enter fourth input manually ?
Please help; Thanks in advance !

There are other ways, but for your case, your approach doesn't seem to be so bad.
If you really want the user to see the original prompt from script.sh, you would have to create an expect program to drive your script; see the man-page for expect.
If you are permitted to change script.sh, you could add the possibility to supply certain parameters from the outside (a file, or an environment variable) and only ask for those parameters which are not supplied. This would IMO be the best approach.

I just found this method and it seems working !
{ echo yes; echo xxxxx; echo xxxx; read rsa; echo $rsa; echo xxxx; } | ./script.sh
Any other way ?

Related

How do you provide specific answers to question prompts from a shell script?

I have a shell script provided by our admin to connect to HPC where I have to provide answers to various prompts every time I connect. Is there a way that I can put my answers in a text file and it provides the answers to the questions based on what question is asked? I tried other answers on SO but here the situation is different because our admin made the questions/options random and sometimes not all questions pop up. Therefor a static input like echo "y n y y y" won't work. Here is the full workflow.
I invoke the script as login.sh then prompt comes up
1) name1 2) name2 2) name3 4) name4
Please select an account:
then I select the number 1 to 4 based on which one I want to connect to. But let's say I always want to connect to name1, and I can simply do that by passing echo "1" | login.sh. However, the tricky part is that these accounts do not appear in the same order each time. Sometimes name1 is on 1, the next time on 4 and so on. It is random. How can I automate it in such a way that I always connect to name1?
Once I pass this first prompt then the next prompt similar to this one comes up
1) instance1
2) instance2
3) instance3
4) random
Please select an instance to connect to:
then again I fill in one numeric value 1 to 4. I always want to connect to random but similar to above, it doesn't always come at position 4. How can I do it?
These first couple of steps are numerical but then comes a bit more complex where it asks us to enter our user id and password.
What is your username?:
here I can either enter my user id or just press enter to continue. I would like to know how to do it both ways. Finally it asks for the password.
Password:
then I enter the password. Trick here is that sometimes it let's me login by only entering the password once, but sometime it asks for the password multiple times.
How can I provide these answers in a simple text file and pass this file to shell script as an argument maybe that it can detect which question is being asked and provide answers based on what question is being asked. I would really appreciate if I can get some guidance on this one.

How can I create a list from a single url and append a numerical value to the end of every line

I need to provide a listing of a website's pages. The only thing to change per line is the page number at the end of the line. So for example, I need to take:
mywebsite.com/things/stuff/?q=content&page=1
And from that generate a sequential listing of pages:
mywebsite.com/things/stuff/?q=content&page=1
mywebsite.com/things/stuff/?q=content&page=2
mywebsite.com/things/stuff/?q=content&page=3
I need to list all pages between 1 - 120.
I have been using bash but any shell that gets the job done is fine. I don't have any code to show because I simply just don't know how to begin. It sounds simple enough but so far I'm completely at a loss as to how I can accomplish this.
With GNU bash 4:
printf '%s\n' 'mywebsite.com/things/stuff/?q=content&page='{1..120}
You can simply use:
for i in $(seq 120); do echo 'mywebsite.com/things/stuff/?q=content&page='"$i"; done > list.txt

Increment Serial Number using EXIF

I am using ExifTool to change the camera body serial number to be a unique serial number for each image in a group of images numbering several hundred. The camera body serial number is being used as a second place, in addition to where the serial number for the image is in IPTC, to put the serial number as it takes a little more effort to remove.
The serial number is in the format ###-###-####-#### where the last four digits is the number to increment. The first three groups of digits do not change for each batch I run. I only need to increment that last group of digits.
EXAMPLE
I if I have 100 images in my first batch, they would be numbered:
811-010-5469-0001, 811-010-5469-0002, 811-010-5469-0003 ... 811-010-5469-0100
I can successfully drag a group of images onto my ExifTool Shortcut that has the values
exiftool(-SerialNumber='001-001-0001-0001')
and it will change the Exif SerialNumber Tag on the images, but have not been successful in what to add to this to have it increment for each image.
I have tried variations on the below without success:
exiftool(-SerialNumber+=001-001-0001-0001)
exiftool(-SerialNumber+='001-001-0001-0001')
I realize most likely ExifTool is seeing these as numbers being subtracted in the first line and seeing the second line as a string. I have also tried:
exiftool(-SerialNumber+='1')
exiftool(-SerialNumber+=1)
just to see if I can even get it to increment with a basic, single digit number. This also has not worked.
Maybe this cannot be incremented this way and I need to use ExifTool from the command line. If so, I am learning the command line/powershell (Windows), but am still weak in this area and would appreciate some pointers to get started there if this is the route I need to take. I am not afraid to use the command line, just would need a bit more hand holding then normal for a starting point. I also am learning Linux and could do this project from there but again, not afraid to use it, just would need a bit more hand holding to get it done.
I do program in PHP, JavaScript and other languages so code is not foreign to me. Just experience in writing it for the command-line.
If further clarification is needed, please let me know in the comments.
Your help and guidance is appreciated!
You'll probably have to go to the command line rather than rely upon drag and drop as this command relies upon ExifTool's advance formatting.
Exiftool "-SerialNumber<001-001-0001-${filesequence;$_=sprintf('%04d', $_+1 )}" <FILE/DIR>
If you want to be more general purpose and to use the original serial number in the file, you could use
Exiftool "-SerialNumber<${SerialNumber}-${filesequence;$_=sprintf('%04d', $_+1 )}" <FILE/DIR>
This will just add the file count to the end of the current serial number in the image, though if you have images from multiple cameras in the same directory, that could get messy.
As for using the command line, you just need to rename to remove the commands in the parens and then either move it to someplace in the command line's path or use the full path to ExifTool.
As for clarification on your previous attempts, the += option is used with numbers and with lists. The SerialNumber tag is usually a string, though that could depend upon where it's being written to.
If I understand your question correctly, something like this should work:
1..100 | % {
$sn = '811-010-5469-{0:D4}' -f $_
# apply $sn
}
or like this (if you iterate over files):
$i = 1
Get-ChildItem 'C:\some\folder' -File | % {
$sn = '811-010-5469-{0:D4}' -f $i
# update EXIF data of current file with $sn
$i++
}

Batch script the same on both PC's but not working?

Hello I have 2 batch files, it works perfectly on one machine but not so perfect on another.
Here is the code.
set /p "ln=" <"C:\LoginSystem\userl.txt"
set "%ln:&="&set "%"
set realuser=%user:"=%
echo %realuser%
So on my machine it shows like this:
echo Liam
Liam
On the other machine it shows like this:
echo "=
"=
It's the exact same machines only difference is one is running Windows 8 (working) and the other windows 7 ("=)
EDIT:
Thank you all for the answers, I managed to solve this by editing the way the userl.txt file is generated to make it display just the name, e.g "Liam" without quotes. Then use this
set /p user=
That seems to work for what I need s there is only 1 value ever going to be in that file.
Thank you all!
A simple echo %thisvariabledoesnoexist:"=% will show the same result.
The reason for the observed output is that the variable %user%, that seems that have to been assigned a value in the set "%ln:&="&set "%" line, did not get any value.
The problem is probably that the input line does not contain the required value or the format of the input line is different from the expected one.
As MC ND has pointed out, the critical point is that variable user must be defined to work properly. If it is not defined, then you get your problem result.
I don't see how identical user1.txt files being processed on two machines with identical batch scripts can possibly give different results as you describe.
Strike that, I can think of one way, but it is a long shot. The assumption is the first two lines are supposed to define the user variable, perhaps along with other variables. But suppose the first two lines do not define the user variable on either machine. Perhaps user is already defined on the machine that "works" before the script is even run, and it is not defined on the other machine. That is the only thing I can come up with that would yield the result you describe.
I do see one thing that concerns me in your code. The following line of code implies that sometimes you get quotes in your input.
set realuser=%user:"=%
You state that quotes in your value interfere, so you remove them. But you are removing them too late! The prior line may not set all the values properly if there are quotes in the value of ln.
Try the following:
set /p "ln=" <"C:\LoginSystem\userl.txt"
set "ln=%ln:"=%"
set "%ln:&="&set "%"
echo %user%

How can I check if a string is a valid file name for windows using R?

I've been writing a program in R that outputs randomization schemes for a research project I'm working on with a few other people this summer, and I'm done with the majority of it, except for one feature. Part of what I've been doing is making it really user friendly, so that the program will prompt the user for certain pieces of information, and therefore know what needs to be randomized. I have it set up to check every piece of user input to make sure it's a valid input, and give an error message/prompt the user again if it's not. The only thing I can't quite figure out is how to get it to check whether or not the file name for the .csv output is valid. Does anyone know if there is a way to get R to check if a string makes a valid windows file name? Thanks!
These characters aren't allowed: /\:*?"<>|. So warn the user if it contains any of those.
Some other names are also disallowed: COM, AUX, NUL, COM1 to COM9, LPT1 to LPT9.
You probably want to check that the filename is valid using a regular expression. See this other answer for a Java example that should take minimal tweaking to work in R.
https://stackoverflow.com/a/6804755/134830
You may also want to check the filename length (260 characters for maximum portability, though longer names are allowed on some systems).
Finally, in R, if you try to create a file in a directory that doesn't exist, it will still fail, so you need to split the name up into the filename and directory name (using basename and dirname) and try to create the directory first, if necessary.
That said, David Heffernan gives good advice in his comment to let Windows do the wok in deciding whether or not it can create the file: you don't want to erroneously tell the user that a filename is invalid.
You want something a little like this:
nice_file_create <- function(filename)
{
directory_name <- dirname(filename)
if(!file.exists(directory_name))
{
ok <- dir.create(directory_name)
if(!ok)
{
warning("The directory of that path could not be created.")
return(invisible())
}
}
tryCatch(
file.create(filename),
error = function(e)
{
warning("The file could not be created.")
}
)
}
But test it thoroughly first! There are all sorts of edge cases where things can fall over: try UNC network path names, "~", and paths with "." and ".." in them.
I'd suggest that the easiest way to make sure a filename is valid is to use fs::path_sanitize().
It removes control characters, reserved characters, and Windows-reserved filenames, truncating the string at 255 bytes in length.

Resources