Menu Driven Shell Script bash - linux

As a complete novice to this i am trying to make a Shell Script. This will be driven by a menu with options such as delete file. The part i am scuppered by is for example, when the menu is up, how to get from pressing '1', to actually creating a new file (as this is option 1 on my menu) I appreciate this may not be the easiest of questions to understand as my use of technical terms is limited, however i would appreciate any help. Below is an example of the first section of my menu. I feel once i know where to start i'll be fine
Menu
[1] Create File
[2] Delete File
[3] Rename file

Try doing this for example :
select x in "Create File" "Delete File" "Rename file"; do
echo "$x choosen"
break
done
Sample output
1) Create File
2) Delete File
3) Rename file
>
Search select in the conditional construct paragraph here
Going further
To run some specific tasks with the result of the $x variable, you can use the case statement (like switch in other languages) like this :
case $x in
Create*) touch file.txt ;;
Delete*) rm -f file.txt ;;
Rename*) mv file.txt file_old.txt ;;
esac

You can do it using switch/case statement. Please have a look on the bash manual or look for similar examples on the Web. Just google "switch case shell example"
Good luck

Related

How can I open a work space from the command line in i3?

I'd like to script opening a workspace with the 'next' available number and then have open in that workspace maybe a two windows each already pointed at a specific view. Any pointers on how to do that? Is i3 actually scriptable in this regard? I have only just started using i3 and loving it, just want to now have it do things I need on a regular basis ;-)
All of i3's "scripting" that isn't already in the config is done through i3-msg
i3-msg sends messages to i3 window manager. It's mostly config lines(or IPC, which is a bit harder).
How can I open a work space from the command line in i3
How do you open it in your config?
bindsym Mod4+1 workspace $ws1
Something like that right? Now, using i3-msg to move to workspace 1:
i3-msg workspace 1
Simple, right?
The rest of your question is pretty unclear, but I'll do my best:
I'd like to script opening a workspace with the "next" available number"
How you'll start out with doing that is(after doing man i3-msg):
i3-msg -t get_workspaces
This returns a json(if you've done any coding you'll feel warm inside and if not you're going to be scared by the output). Then I'm going to ask you to read up on this:
https://i3wm.org/docs/ipc.html#_receiving_replies_from_i3
Using jq or something like json.sh to parse through the output with bash, you should get which workspaces are "active", example:
[{"num":3,"name":"3","visible":true,"focused":false,"rect":{"x":0,"y":0,"width":1920,"height":1080},"output":"HDMI-1","urgent":false},{"num":2,"name":"2","visible":true,"focused":false,"rect":{"x":3520,"y":0,"width":1920,"height":1080},"output":"VGA-1","urgent":false},{"num":1,"name":"1","visible":true,"focused":true,"rect":{"x":1920,"y":32,"width":1600,"height":868},"output":"eDP-1","urgent":false},{"num":5,"name":"5","visible":false,"focused":false,"rect":{"x":1920,"y":32,"width":1600,"height":868},"output":"eDP-1","urgent":false}]
Reading through the website I gave you, you can see, workspaces 1,2,3 and 5 are "active" aka have windows in them. After parsing the actual json you'll end up with an array or something of this. If you want to spawn on 4(the real "next" desktop) or 6 (aka biggest number + 1) is up to you. You didn't mention what you want to script it in, so I'll leave that to you to figure out.
maybe two windows each already pointed at a specific view
I'm not sure what you mean. You probably want 2 windows of X(we'll use a terminal in this case) in the workspace we've determined as "next" ?
Let's go back to i3-msg for a bit.
Imagine you doing whatever you're trying to do, manually, as a list of commands you're firing to i3.
"Go to workspace X" : i3-msg workspace 4
"Spawn a program called kitty there": kitty
"Split vertically and spawn another program": i3-msg split v
"Spawn another kitty window": kitty
After that you can get back to your current workspace(I suggest saving it in a variable and just reusing i3-msg workspace $curr_workspace).
As I said, the question wasn't about the actual scripting so I left that out to figure it out on your own, but don't hesitate to ask a concrete question under the bash tag. :). Hopefully I didn't completely misunderstand your question.
Welcome to the i3 community.
#Nephilim's post is excellent. Just to add a trick to the toolbox...
Sometimes you might want to script some action relative to a particular window. Like:
Give me a test environment next to this browser.
You can get the window ID by running xwininfo and clicking the window that you want to anchor your automation to. The window ID can be used as a parameter to i3-msg.
For example, running the command below will let you select a window and then will set that window's width to 1000:
i3-msg "[id=$(
xwininfo \
| sed -n 's/.*Window id: \(0x[0-9a-f]*\).*/\1/p'
)] resize set 1000"

How can I enter text into Launchy and append it to the end of a text file?

I'm a Debian Stretch user coming from Windows. In Windows with the launchy app (also available for Linux), I had a method of entering text into launchy that was then appended to the end of a .txt or .md file.
To do this in Windows, I created a file called note.bat that contained the following:
echo %*>>"C:\collectednotes.md"
I'd make launchy aware of note.bat by adding its containing folder to “Launchy” → “Settings” → “Catalog” and adding filetype *.bat.
From there, I'd launch launchy, type note, hit Tab, enter some text, hit Enter, and then the text would be added to the end of collectednotes.md.
A mostly working process is detailed in my answer below. I'll give the green checkmark answer to anyone that can adjust this process (via note.sh and/or launchy plugin setup detailed below) to appropriately handle all special characters.
This may contain the solution to this question:
Which characters need to be escaped in Bash? How do we know it?
Solved (almost). I'm keeping this question unanswered and will give to whoever completes the remaining ~5%. Steps to get the 95% solution with xfce4-terminal version 0.8.3-1:
Install launchy and launchy-plugins (both are version 2.5-4 for me):
apt-get install launchy
apt-get install launchy-plugins
Open terminal to default location of ~/ and create collectednotes.md:
echo "# Launchy Notes Collected Here" > collectednotes.md
Create note.sh shell script:
echo '#!/bin/sh' > note.sh
Create shell script line 2:
echo ALL_ARGUMENTS='"$#"' >> note.sh
Create shell script line 3:
echo 'echo "$ALL_ARGUMENTS" >> ~/collectednotes.md' >> note.sh
If you open note.sh, it will look like:
#!/bin/sh
ALL_ARGUMENTS="$#"
echo "$ALL_ARGUMENTS" >> ~/collectednotes.md
Make note.sh executable:
chmod +x note.sh
Launch launchy and click the gear icon in upper right for settings. If consistency with launchy for Windows is desired, set launchy Hotkey to Alt+Space. If you receive a keyboard shortcut conflict message as I do on Debian with Xfce, first go to Settings, Window Manager, Keyboard tab, and clear Alt+Space as the shortcut for Window operations menu.
Next in launchy settings, go to Plugins tab and enable the plugin Runner. Click the + button and create a new Runner custom command as follows:
- Name: note
- Program: /home/YOURUSERNAMEHERE/note.sh (launchy does not like Program path of ~/note.sh, so a specific path with username is required)
- Arguments: '$$'
Click the Catalog tab and hit Rescan Catalog just in case. Hit OK to close launchy settings.
Now let's test it.
- launch launchy with Alt+Space or your hotkey
- type note (You may have to wait 10 second or so on first run. You'll know things are as expected when you see the text "note" with a orange/yellow icon containing silhouette of a person.)
- hit Tab
- enter some text (no need for single or double quotes or escapes), e.g.: Remember to donate at least $3 to Josh at Launchy https://www.launchy.net/donate.php
- hit Enter
Now open collectednotes.md to confirm the text was captured.
The remaining issues seem to be dealing with single quotes and double quotes. For example, consider the following note:
I don't know what I'd do without Launchy.
Which results in the following in collectednotes.md:
I dont know what Id do without Launchy.
Or:
Would David Allen like universal text capture from anywhere in Linux? My bet is "yes!"
Results in the following in collectednotes.md:
Would David Allen like universal text capture from anywhere in Linux? My bet is \yes!\
Single quoting and/or double quoting the input to launchy doesn't solve it. Note the launchy Runner custom plugin construction component of '$$' is a piece of this puzzle.
I'll give the answer to anyone that can adjust this process (via note.sh and/or launchy plugin setup) to appropriately handle all special characters. Maybe this would add proper escapes to user input with something like gsub.
The rationale for being exacting regarding proper character handling is that this process is useful for copying and logging random chunks of text from web pages, but if common characters like single quotes are not handled as expected, confidence in the system is much reduced.

Create/find batch script which performs a 'find and replace' within a directory and sub-directories, for excel files with varied names

I have many files (Excel/CSV) contained in varied layers of sub-folders under a single directory. Many of the files contain a single cell with a common text string, which all need to be updated to a new string. The files all have different names. How difficult would it be to create a (preferably batch) script to search the entire directory (inclusive of sub-directories) for a given text string, replace all instances with a new string, and leave everything else in its place.
I am new to scripting, I have been searching the site and haven't found a solution that has worked for me. I want to stress that I cannot download, install or run third-party software due to security measures, and so applications like FART are out. Is anybody able to provide and input for the creation of something like this, or link me to such a script that already exists? Thanks in advance!!
Robust text editing using pure batch is difficult and slow.
Unless your admin techs have disabled CSCRIPT, you can use my JREPL.BAT - a hybrid JScript/batch text processing utility.
There is no download or installation process required. JREPL.BAT is pure script that runs natively on any Windows machine from XP onward. Simply copy the script into a new file named JREPL.BAT on your local machine.
Once you have your own copy, then all you need is something like the following command, run from the command console:
for /r "c:\your\root\path" %F in (*.csv) do #jrepl "search string" "replace string" /L /F "%F" /O -
I used the /L switch to treat the search as a literal. You may want to drop the /L switch and do a regular expression search instead.
If you put the command within another script, then you will need to double the percents and use CALL JREPL.
#echo off
for /r "c:\your\root\path" %%F in (*.csv) do call jrepl "search string" "replace string" /L /F "%%F" /O -
Issue the following command from the console prompt to get full documentation:
jrepl /? | more
I configure my console window with a large buffer height so I can scroll back to see prior output, thus I don't need | more when I look at the help.

Interactive quiz in Bash (Multiple Q's)

I'm teaching an introductory Linux course and have abandoned the paper-based multiple-choice quizzes and have created interactive quizzes in Bash. My quiz script is functional, but kind of quick-and-dirty, and now I'm in the improvement phase and looking for suggestions.
First off, I'm not looking to automate the grading, which certainly simplifies things.
Currently, I have a different script file for each quiz, and the questions are hard-coded. That's obviously terrible, so I created a .txt file holding the questions, delimited by lines with "question 01" etc. I can loop through and use sed -n "/^quest.*$i\$/,/^quest.*$(($i+1))\$/p", but this prints the delimiter lines. I can pipe through sed "/^q/d" or head -n-1|tail -n+2 to get rid of them, but is there a better way?
Second issue: For questions where the answer is an actual command, I'm printing a [user]$ prompt, but for short-answer, I'm using a >. In my text file, for each question, the last line is the prompt to use. Initially, I was thinking I could store the question in a variable and |tail -1 it to get the prompt, but duh, when you store it it strips newlines. I want the cursor to immediately follow the prompt, so I either need to pass it to read -p or strip the final newline from the output. (Or create some marker in the file to differentiate between the $ and > prompt.) One thought I had was to store each question in a separate file and just cat it to display it, making sure there was no newline at the end. That might be kind of a pain to maintain, but it would solve both problems. Thoughts?
Now to how I'm actually running the quiz. This is a Fedora 20 box, and I tried copying bash and setuid-ing it to me so that it would be able to read the quiz script that the students couldn't normally read, but I couldn't get that to work. After some trial and error, I ended up copying touch and setuid-ing it to me, then using that to create their answer file in a "submit" directory with an ACL so new files have o=w so they can write to their answer file (in the quiz with >> echo) but not read it back or access the directory. The only major loophole I see with this is that they can delete their file by name and start the quiz over with no record of having done so. Since I'm not doing any automatic grading, I'm not terribly concerned with the students being able to read the script file, although if I'm storing the questions separately, I suppose I could make a copy of cat and setuid it to read in files that they can't access.
Also, I realize that Bash is not the best choice for this, and learning the required simple input/output for Python or something better would not take much effort. Perhaps that's my next step.
1) You could use
sed -n "/^quest.*$i\$/,/^quest.*$(($i+1))\$/ { //!p }"
Here // repeats the last attempted pattern, which is the opening pattern in the first line of the range and the closing pattern for the rest.
...by the way, if you really want to do this with sed, you better be damn sure that i is a number, or you'll run into code injection problems.
2) You can store multiline command output in a variable without problems. You just have to make sure you quote the variable everafter to avoid shell expansion on it. For example,
QUESTION=$(sed -n "/^quest.*$i\$/,/^quest.*$(($i+1))\$/ { //!p }" questions.txt)
echo -n "$QUESTION" # <-- the double quotes are important here.
The -n option to echo tells echo to not append a newline at the end, which should take care of your prompt problem.
3) Yes, well, hackery breeds more hackery. If you want to lock this down, the first order of business would be to not give students a shell on the test machine. You could put your script behind inetd and have the students fill it out with telnet or something, I suppose, but...really, why bash? If it were me, I'd knock something together with a web server and one of the several gazillion php web quiz frameworks. Although I also have to wonder why it's a problem if students can see the questions and the answers they gave. It's not like all students use the same account and can see each other's answers, is it? (is it?) Don't store an answer key on the same machine and you shouldn't have a problem.

Associate one File to another File in linux

We have application which is written in Python in linux enviromet which is legacy code.I have task to document which help other in wiki page. I thought, Can I add one file into Existing code. So I can add documentation into another File. So if user open file it will pop us with code detail. if user does not want to see that file they can close this File. for Example
sample.py ( A File which contain code)
demo.txt ( which contain documentation file)
So if I open sample.py using vi like vi sample.py than demo.txt open by default like pop us or simple way which contain documentation part. I think it is like windows tool when we open tool it pop us infront of user. it is my idea I am not sure really it is valid or not. I have searched but could not find any useful information.
What you want to do will most likely confuse the user. If one types vi sample.py one expects to read this file. Now what you can do as #HAL said in his comment is add a comment in your code saying that the documentation for this code is in the demo.txt accessible at /path/to/demo.txt.
I think this is the common way to do it, and you will probably frustrate the user if you don't do it this way. (at least I would be ;) )
I am not aware of any Linux specific include functionality and I do not think that it exists, because the program you are executing is vi and not the Linux kernel. But editors support editor specific functions for hyper links. Here is an example for vim. vim: Add clickable label
Another way would be to replace vi with a shell script which does what you want. This is an example:
#! /bin/bash
if [ "$1" = "sample.py" ] ; then
vim demo.txt "$1"
fi
This will open the documentation together with the program in two vim buffers.

Resources