Ksh - Script: List Files and store as variable - shell

I'm using kshon an HP-UX box.
In a portion of my script, I want to list certain files (*.xml), have them numbered and have the user choose a file by typing the number and hitting enter. That filename will then be stored as a variable.
Example of output:
Please choose a file:
1) bar27.xml
2) foo1.xml
3) foobar4.xml
Then the user types in 1, 2, or 3 and hit enter. The file name chosen needs to be stored as a variable. So if the user chooses 2 the variable should contain foo1.xml.

I've come up with the following which works:
files=$(ls *.xml)
i=1
for j in $files
do
echo "$i) $j"
file[i]=$j
i=$(( i + 1 ))
done
echo "Choose an XML file from above to use:"
read v_CHOOSELIST
echo "File chosen: ${file[$v_CHOOSELIST]}"

Related

Bash Variable Not Being Assigned

I have this bash script, that gets an input from the user, and returns a phonetic transcription of the word, even if no transcription is available. However, the variable results isn't being assigned as a blank line is being printed instead of the value inside.
I have tried putting the commands into a different script, and that also produced blank lines, and doubled checked that there was no space between results and =
Code:
#!/usr/bin/env bash
#check if user entered a word to translate to ipa
#if a word was not entered prompt the user to enter a word
#else set the word passed as an argument to the variable current
if [ -z "$1" ]
then
echo "You did not enter a word for translation, Please enter one now: "
read current
else
current=$1
fi
#confirm to user the word they entered
echo "The word you chose for translation: $current"
#format the word into '< w o r d >'
onmt_word=$(python ONMT_DATA_FORMAT.py "$current")
#write over current word in temp_word.txt
echo $onmt_word > temp_word.txt
#translate the word in temp_word.txt using openNMT with the model created from a set of 32k words
results=$(onmt_translate -gpu -1 -model eng_ipa_model1_steps/eng_ipa_model1_step_100000.pt -src temp_word.txt -replace_unk -verbose -output model1_step_10000_temp_pred)
#print only the results we care about, i.e. the translated IPA
echo "The provided IPA translation is:"
echo $results | egrep -o '< .* >'
echo "Please ignore the first and last symbol, these are needed for the translation process."
Source:
https://github.com/LonelyRider-cs/LING4100_project

shell - How to define a variable in a C-type for loop?

I want to iterate over an array of file names stored in files_arr to create a terminal-based file manager in the POSIX shell.
A reduced version of the functions list_directory looks like this:
# Presents the user with the files in the directory
list_directory() {
# Iterate over each element in array `files_arr` by index, not by filename!
# And outputs the file name one on each line
for file in "${!files_arr[#]}"; do
echo "${files_arr[file]}"
done
}
I want to implement a way to exclude the first n files from the array files_arr.
n is defined by how often the user scrolls past the current terminal window size to create an effect of scrolling through the files, highlighting the file where the cursor is currently on.
On a directory (e.g. the home directory) that looks like this:
To Implement this I try to create an C-like for loop like so:
for ((file=$first_file; file<=${!files_arr[#]}; file=$((file+1))); do
or as the whole function:
# Presents the user with the files in the directory
list_directory() {
# Iterate over each element in array `files_arr` by index, not by filename!
#for file in "${!files_arr[#]}"; do
for ((file=$first_file; file<=${!files_arr[#]}; file=$((file+1))); do
# Highlighted file is echoed with background color
if [ $file -eq $highlight_index ]; then
echo "${BG_BLUE}${files_arr[file]}${BG_NC}"
# Colorize output based on filetype (directory, executable,...)
else
if [ -d "${files_arr[file]}" ]; then
echo "$FG_DIRECTORY${files_arr[file]}$FG_NC"
elif [ -x "${files_arr[file]}" ]; then
echo "$FG_EXECUTABLE${files_arr[file]}$FG_NC"
else
echo "${files_arr[file]}"
fi
fi
# $LINES is the terminal height (e.g. 23 lines)
if [ "$file" = "$LINES"]; then
break
fi
done
}
which returns the error:
./scroll.sh: line 137: syntax error near `;'
./scroll.sh: line 137: ` for ((file=$first_file; $file<=${!files_arr[#]}; file=$((file+1))); do'
How can I iterate over the array files_arr, defining the start-index of $file?
You can iterate over the array with:
for (( i = $first_file; i < ${#files_arr[#]}; i++ )); do
echo ${files_arr[i]}
done
but it seems cleaner to use:
for file in ${files_arr[#]:$first_file}; do
echo "$file"
done

Menu based shell script to delete files

My requirement is to delete file based on it displayed. Following is code snippet where I listed files but when I select option it displays file and when I capture file name its not happening only getting key not VALUE($REPLY only displays key but not value). Can someone help me out.
#!/bin/bash
select list in $(ls *.tmp)
do
echo $list
echo Do you want to delete files ?
read userInput
echo "UserInput is :: " $userInput
echo "Reply is :: " $REPLY
if [ $userInput == $REPLY ] ; then
# rm $REPLY
echo 'Yes'
break
done
----OUTPUT-----
1) +~JF1905393034413613060.tmp
2) +~JF2032005334435574091.tmp
3) +~JF3116454937363220082.tmp
4) +~JF3334986634800781310.tmp
5) +~JF3651229840772890748.tmp
6) +~JF3882306323060007639.tmp
7) +~JF573641658479505435.tmp
8) +~JF6137053351660236007.tmp
9) +~JF6277682393160684532.tmp
10) +~JF6385610668752278364.tmp
11) +~JF6824954027739238354.tmp
12) +~JF7876557427734797684.tmp
#? 4
+~JF3334986634800781310.tmp
Do you want to delete files ?
y
UserInput is :: y
Reply is :: 4
No
Try this:
PS3="Pick a file number to delete (or Ctrl-C to quit): "
select f in *.tmp ; do echo rm "$f" ; done
Then remove the echo to make it actually delete files.

A bash script to split a data file into many sub-files as per an index file using dd

I have a large data file that contains many joint files.
It has an separate index file has that file name, start + end byte of each file within the data file.
I'm needing help in creating a bash script to split the large file into it's 1000's of sub files.
Data File : fileafilebfilec etc
Index File:
filename.png<0>3049
folder\filename2.png<3049>6136.
I guess this needs to loop through each line of the index file, then using dd to extract the relevant bytes into a file. Maybe a fiddly part might be the folder structure bracket being windows style rather than linux style.
Any help much appreciated.
while read p; do
q=${p#*<}
startbyte=${q%>*}
endbyte=${q#*>}
filename=${p%<*}
count=$(($endbyte - $startbyte))
toprint="processing $filename startbyte: $startbyte endbyte: $endbyte count: $c$
echo $toprint
done <indexfile
Worked it out :-) FYI:
while read p; do
#sort out variables
q=${p#*<}
startbyte=${q%>*}
endbyte=${q#*>}
filename=${p%<*}
count=$(($endbyte - $startbyte))
#let it know we're working
toprint="processing $filename startbyte: $startbyte endbyte: $endbyte count: $c$
echo $toprint
if [[ $filename == *"/"* ]]; then
echo "have found /"
directory=${filename%/*}
#if no directory exists, create it
if [ ! -d "$directory" ]; then
# Control will enter here if $directory doesn't exist.
echo "directory not found - creating one"
mkdir ~/etg/$directory
fi
fi
dd skip=$startbyte count=$count if=~/etg/largefile of=~/etg/$filename bs=1
done <indexfile

How to print and edit variable content at the same place on runtime of a Unix shell script?

I have been looking all around (with no avail) to perform the following:
I want to display and able to edit if necessary the content of a variable in runtime for a Unix shell script after giving it a value. The idea goes like this:
Suppose we have a variable value either defined in script or by user input
var=12345
Print the variable value, but also leave the cursor in that position of printing and either press just enter to leave it intact or enter a new value in runtime
Edit variable content (press Enter to leave intact) : 12345
at this point at runtime, I want to leave the cursor in the position of number 1, while showing the variable, and working in the way that if I press Enter, leave the original content (12345) or read for a new value in that same place and modify. Clearing the display of the variable when typing anything else than Enter would be a big plus.
I have looked all around for a way to do this, but just haven't found anything. Anyone willing to provide a solution?
I would suggest you doing this in another way:
var=12345
echo "Change the value of Var (current value: $var)"
read -p "New value (Press Enter to skip):" nvar
if [[ "$nvar" != "" ]]; then
var="$nvar"
fi
echo $var
with this, it will prompt:
Change the value of Var (current value: 12345)
New value (Press Enter to skip):
what you wanted in the question (without the "big plus" part), could be achieved too:
var=12345
echo -ne "Now you may want to change the value: \n$var\r"
read nvar
if [[ "$nvar" != "" ]]; then
var="$nvar"
fi
echo $var
with this, it will prompt (cursor sits between ** )
Now you may want to change the value:
*1*2345
With bash, you could use the readline option for read, but that does not put the cursor at the beginning. It does however do what you want
var=12345
read -ep "Enter new value: " -i $var var
If you need the cursor to go back, you can do this:
var=12345
prompt="Enter new value: $var"
for ((i=1; i<=${#var}; i++)); do prompt+=$'\b'; done
read -p "$prompt" new
[[ -z $new ]] && new=$var

Resources