Trying to get the directory name from a users choice array - bash

I built this array to list a directory's contents that would allow the user to input a number instead of the exact directory name. I do not know how I can get the picked directory's name from the input which is only a number? I need it to identify what exact directory was picked from the array that will be used. Thanks to all those willing to help.
if [ -d $TDDIR ]; then
# List folders in $TDDIR
VAR1=1
FILES=( `ls $TDDIR` )
FILECNT=${#FILES[*]}
# List number of folders available
clear
echo "Current list of folders to pick from."
echo
while [ $VAR1 -lt $FILECNT ]; do
echo -e "[$VAR1] \t ${FILES[VAR1]}"
let "VAR1 += 1"
done
# Reduce VAR1 by one
let "VAR1 -= 1"
# Have user choose which to use for scan
read -p "Which file would you like to scan 1 - $VAR1 or 0 to exit? :" INPUT
if [ $INPUT -eq '0' ]; then
echo "You chose to quit. Exiting now."
sleep 2
exit 0
fi
while (( $INPUT > $FILECNT || $INPUT < 1 || $INPUT > $VAR1 )); do
echo
echo "You selected $INPUT."
read -p "$INPUT is not valid. Choose a valid option: " INPUT
done
else exit
fi

echo ${FILES[(($VAR - 1))]}
The -1 is because the index for bash arrays starts from 0.
A side note, ls is not appropriate for the task (see: Parsing ls outputs)
Also, you may try using select for the menu (see: Bash Script Menus and Functions)

Related

Unix shell script problem with space in the file name

I an new to shell scripting. We have a requirement to write a shell
script for below requirement. We will get daily files in the below
format.
1. /app/dstage/BAL/Activ Bal_pen_20200129.xls
2. /app/dstage/BAL/Activ Bal_pen_20200130.xls
3. /app/dstage/BAL/Activ Bal_pen_20200131.xls We need to write a shell script as soon as the files arrvies in the > direcotry I need move
them to another staging directory. I am writing below script. However
i am getting message file not found even the file "Activ
Bal_pen_20200129.xls" present in the directory. I am seeing the
problem is with the space in the file name. How to resolve the space
issue in the file name. my Script is below:
#!/bin/ksh
# Validation the number of arguments
if (( $# == 4 )); then
Pattern=$1
numFilesExpected=$2
stgDir=$3
maxWaitTime=$4
else
print -u2 "Wrong number of arguments (${#}): Usage FileValidation.ksh <Pattern> <numFilesExpected> <stgDir> <maxWaitTime>"
return 8
fi
# While max waiting duration is not obtained find files and set the array containing the file names; closing STDERR in case no files are found
waitTime=0
while (( $waitTime < $maxWaitTime )) ; do
set -A fileList $(ls $Pattern 2<&-)
if (( ${#fileList[#]} != 0 )); then
break
fi
sleep 5
((waitTime++))
done
# Resetting the fileList in case it did not go in the loop
set -A fileList $(ls $Pattern 2<&-)
# Verifying if the pattern returned a file
if (( ${#fileList[#]} == 0 )); then
print -u2 "No file found with pattern: $Pattern"
return 1
#
elif [[ $(basename "$Pattern") = "*" ]]; then
print -u2 "Found a source file pattern with no prefix (only a path with wildcard *): $Pattern"
return 1
# Validation of the number of files expected
elif (( $numFilesExpected != 0 && ${#fileList[#]} != $numFilesExpected )); then
print -n "${#fileList[#]}"
return 2
fi

Difficulty in mentioning multiple calls in a single line of echo

The problem I have is with echo cannot echo e.g: "$prefix_$suffix". This is a assignment for a class in school if that changes things.
I've tried e.g "$prefix _$suffix" but that creates a space between the prefix and suffix
#!bin/bash
read -p "Username prefix: " prefix
read -p "Amount of users: " amount
read -p "Name of file to store, include extension (e.g test.txt): " filename
touch "$filename"
new="$amount"
suffix=0
state=true
while [ state=true ] ; do
#in this function i reverse the user input amount of users so it appears as user 1,2,3 (and so on) in the first line of the text file that is also user input.
if [ "$new" -ge 1 ] ; then
newpass="$(gpg --gen-random --armor 1 12)"
#reversing process, making the suffix start at 1 so user 1 gets assigned suffix 1 for the username and i decrease the "new" variable that gets set to "$amount" so the while loop isn't indefinite
new=`expr "$new" - 1`
suffix=`expr "$suffix" + 1`
echo -n "$prefix" >> "$filename"
echo -n "_$suffix" >> "$filename"
echo -n " " >> "$filename"
echo "$newpass" >> "$filename"
echo -e >> "$filename"
elif [ "$new" -eq 0 ] ; then
break
fi
done
a run of this bash results in 5 lines e.g:
re_1 UlrZW3jB5L9zt6Nf
and so on, depending how many users you choose at the input
however the next task is to create users with the username, in this example re_1 with the password: UlrZW3jB5L9zt6Nf. This is where the clunky echo stuff I've done doesn't work. I tried doing useradd -u "$prefix_$suffix" and "$prefix $suffix" , none of these work since "$prefix$suffix" is treated as one call instead of two and the "$prefix _$suffix" adds one space in between the prefix and suffix which is not acceptable.
Even if this looks very introverted to you, hence i added comments to make it understandable, help is very appreciated.
Feel free to ask question if you do not understand and want to help!
This will do what you want:
echo "${prefix}_${suffix}"

How to remove contact from shell script?

I am creating a simple phonebook using unix shell scripts. I have gotten all of my functions to work except the removal of a contact after it has been created. I have tried combining grep and sed in order to accomplish this, but cannot seem to get over the hump. The removal shell i've tried is as follows.
#!/bin/sh
#removeContact.sh
echo “Remove Submenu”
echo “Please input First Name:”
read nameFirst
echo “Please input Last Name:”
read nameLast
x=$(grep -e “$nameFirst” -e “$nameLast” ContactList)
echo $x
sed '/'$x'/ d' ContactList;
echo “$nameFirst $nameLast is removed from your contacts”
exit 0
I'm not sure if I am declaring x incorrectly, or if my syntax is wrong when sed is used.
Any help would be greatly appreciated. Thank you.
#!/bin/bash
ContactList="contacts.txt"
export ContactList
exit=0
while [ $exit -ne 1 ]
do
echo "Main Menu"
echo "(a) Add a Contact"
echo "(r) Remove a Contact"
echo "(s) Search a Contact"
echo "(d) Display All Contact’s Information"
echo "(e) Exit"
echo "Your Choice?"
read choice
if [ "$choice" = "a" ]
then
./addContact.sh
elif [ "$choice" = "r" ]
then
./removeContact.sh
elif [ "$choice" = "s" ]
then
./searchContact.sh
elif [ "$choice" = "d" ]
then
./displayContact.sh
elif [ "$choice" = "e" ]
then
exit=1
else
echo "Error"
sleep 2
fi
done
exit 0
#!/bin/sh
#addContact.sh
ContactList="contacts.txt"
echo “Please input First Name:”
read nameFirst
echo “Please input Last Name:”
read nameLast
echo “Please input Phone Number:”
read number
echo “Please Input Address”
read address
echo “Please input Email:”
read email
echo $nameFirst:$nameLast:$number:$address:$email>> ContactList;
echo "A new contact is added to your book."
exit 0
sed '/'$x'/ d' ContactList
won't remove anything from the file ContactList, it will simply output the changes to standard output.
If you want to edit the file in-place, you'll need the -i flag (easy) or to make a temporary file which is then copied back over ContactList (not so easy, but needed if your sed has no in-place editing option).
In addition, since ContactList is a shell variable referencing the real file contacts.txt, you'll need to use $ContactList.
And, as a final note, since you're using the full line content to do deletion, the presence of an address like 1/15 Station St is going to royally screw up your sed command by virtue of the fact it contains the / character.
I would suggest using awk rather than sed for this task since it's much better suited to field-based data. With the record layout:
$nameFirst:$nameLast:$number:$address:$email
you could remove an entry with something like (including my patented paranoid perfect protection policy):
cp contacts.txt contacts.txt.$(date +%Y.%m.%d.%H.%M.%S_$$)
awk <contacts.txt >tmp.$$ -F: "-vF=$nameFirst" "-vL=$nameLast" '
F != $1 || L != $2 {print}'
mv tmp.$$ contacts.txt

How to list files with words exceeding n characters in all subdirectories

I have to write a shell script that creates a file containing the name of each text files from a folder (given as parameter) and it's subfolders that contain words longer than n characters (read n from keyboard).
I wrote the following code so far :
#!/bin/bash
Verifies if the first given parameter is a folder:
if [ ! -d $1 ]
then echo $1 is not a directory\!
exit 1
fi
Reading n
echo -n "Give the number n: "
read n
echo "You entered: $n"
Destination where to write the name of the files:
destinatie="destinatie"
the actual part that i think it makes me problems:
nr=0;
#while read line;
#do
for fisier in `find $1 -type f`
do
counter=0
for word in $(<$fisier);
do
file=`basename "$fisier"`
length=`expr length $word`
echo "$length"
if [ $length -gt $n ];
then counter=$(($counter+1))
fi
done
if [ $counter -gt $nr ];
then echo "$file" >> $destinatie
fi
done
break
done
exit
The script works but it does a few more steps that i don't need.It seems like it reads some files more than 1 time. If anyone can help me please?
Does this help?
egrep -lr "\w{$n,}" $1/* >$destinatie
Some explanation:
\w means: a character that words consist of
{$n,} means: number of consecutive characters is at least $n
Option -l lists files and does not print the grepped text and -r performs a recursive scan on your directory in $1
Edit:
a bit more complete version around the egrep command:
#!/bin/bash
die() { echo "$#" 1>&2 ; exit 1; }
[ -z "$1" ] && die "which directory to scan?"
dir="$1"
[ -d "$dir" ] || die "$dir isn't a directory"
echo -n "Give the number n: "
read n
echo "You entered: $n"
[ $n -le 0 ] && die "the number should be > 0"
destinatie="destinatie"
egrep -lr "\w{$n,}" "$dir"/* | while read f; do basename "$f"; done >$destinatie
This code has syntax errors, probably leftovers from your commented-out while loop: It would be best to remove the last 3 lines: done causes the error, break and exit are unnecessary as there is nothing to break out from and the program always terminates at its end.
The program appears to output files multiple times because you just append to $destinatie. You could simply delete that file when you start:
rm "$destinatie"
You echo the numbers to stdout (echo "$length") and the file names to $destinatie (echo "$file" >> $destinatie). I do not know if that is intentional.
I found the problem.The problem was the directory in which i was searching.Because i worked on the files from the direcotry and modified them , it seems that there remained some files which were not displayed in file explorer but the script would find them.i created another directory and i gived it as parameter and it works. Thank you for your answers
.

Rotate a set of logfiles named file, file.0, file.1, etc. in shell script

I have a directory full of log files that I need to rotate using a posix shell script on an embedded system. They are named file, file.0, file.1 and so on. I didn't see this question already asked and had trouble finding it on google.
I ended up solving this myself, and thought I should post the solution here. If anyone has suggestions for improvement, feel free to add them.
# Usage: rotate_logs base [max]
# Example:
# rotate_logs messages 10 # Rotate "messages" files keeping only 10 rotated files.
rotate_logs() {
#set -x
local base="$1"
# ensure we have a base and it is not null
if [ $# -lt 1 -o -z "$1" ]; then
echo "Usage: $0 base [max]" >&2
echo "Example:" >&2
echo -e "\t$0 messages 10\t# Rotate \"messages\" files keeping only 10 rotated files." >&2
return 1
fi
# see if we were given a max number and make sure it is a number
if [ $# -ge 2 ]; then
if ! echo "$2" | egrep -q '^[0-9]+$'; then
echo "Maximum number, \"$2\", must be a number." >&2
return 1
fi
local max=$2
fi
local i
local n
# Get a list of all of the already rotated files in reverse
# base.3 base.2 base.1
for i in $(ls -1r "$base".*); do
# Calculate the next number for the current file, i.e. 4 for base.3
n=$((1 + $(echo $i | sed 's,'"$base"'.,,')))
# If the new file number is greater than max, delete it.
if [ $n -gt ${max:-999999} ]; then
rm -rf "$i"
else
# otherwise move the file to the new number
mv $i "$base".$n
fi
done
# If there is a "base" file with no extension move that now.
if [ -e "$base" ]; then
mv "$base" "$base".0
fi
}

Resources