find a file in a folder using a bash script (linux) - linux

need to create a text file within the folder (done)
I use nano to create a file called spn.txt and input some data inside. (done)
4:3
5:5
1:5
3:1
4:3
4:1
create a script
2.1. ask user to input the name of the text file (txt) in the folder
2.2 find the txt file
if there no file found
ask user to input the name of the text file (txt) in the folder
2.3. if have the file read the value of the file and display the number of the left hand side
#!/bin/bash
echo "please input file name with extension (e.g spn.txt)"
read filename
how to create a while command that
look for the filename
if filename not found in the folder, ask user to input file name
if file name is found. display the number of the left hand side.

Disclaimer: this does not define a loop and hence maybe does not answer your question.
This said, if you need to quickly manage some user interactions you can try Zenity
#!/bin/bash
FILE=`zenity --file-selection --title="Select a File"`
case $? in
0)
echo "\"$FILE\" selected.";;
1)
echo "No file selected.";;
-1)
echo "An unexpected error has occurred.";;
esac
Obviously, you need Zenity to be installed, which can be a problem regarding the portability. The advantage is that you can create "complex" input forms. It all depends on your context.

You can easily achieve this with the following commands:
#!/bin/bash
filename=""
echo -e "\nStarting script ... You can press Ctrl+C anytime to stop program execution.\n"
##### Ensure the user will provide a valid file name #################
while [[ ! -r "${filename}" ]] ; do
echo -n "Please, enter the file name: (e.g spn.txt): "
read filename
done
#
# At this point we have a valid filename supplied by the user
# So, prints the left values of it, using the ':' as a field delimiter
cut -d':' -f 1 ${filename}
The cut command is used above with the following parameters:
-d':' -> Set the delimiter to ':'
-f 1 -> Display just the field number 1. If you would like to display just the right numbers, you could use -f 2 here, because assuming the field delimiter is the character ':', the right numbers are located on the second field.

#!/bin/bash
### Maintainer: Vrej Abramian, Git: https://github.com/vrej-ab, vrejab#gmail.com ###
### Configuration Parameters Start ###
request_filename_message="Please input file name with extension (e.g spn.txt): "
filename_variable='filename'
attempts_count='3'
_file_check='' # Leave this empty
### Configuration Parameters End ###
### Finctions Start ###
# Unified messages
echo_green(){ echo -en "\033[0;32m$*" ;echo -e "\033[0;0m"; }
echo_yellow(){ echo -en "\033[1;33m$*" ;echo -e "\033[0;0m"; }
echo_red(){ echo -en "\033[0;31m$*" ;echo -e "\033[0;0m"; }
# Promt and request to input a valid `filename`
request_filename_function(){
# Use `read` with `-p` option which will prompt your message and
# avoid using extra `echo` command.
read -p "${request_filename_message}" "${filename_variable}"
}
# Check if the inputed filename is accessible
file_check(){
if [ -r "${!filename_variable}" ] ;then
echo_green "\n[INFO]: ${!filename_variable} - file is available."
_file_check='pass'
else
echo_red "\n[ERROR]: ${!filename_variable} - file is either un-available or un-accessible."
_file_check='fail'
fi
}
# If provided `filename` wouldn't be available, this provides retrying chances
retry_function(){
local i=1
while [ "${_file_check}" != 'pass' ] && [ ${i} -lt ${attempts_count} ] ;do
echo_yellow "\n[WARN]: Please tray again - $(( attempts_count-i )) times left!"
local i=$(( ++i ))
request_filename_function
file_check
done
if [ ${i} -gt ${attempts_count} ] ;then
echo_red "[FATAL]: No more attempts, Bye-Bye...\n"
exit 1
fi
}
# Get the provided file's first column data - assuming that the delimiter is a ':' character in the file
left_handside_numbers_function(){
cat "${1}" | awk -F':' '{print $1}'
}
# Filter the user defined param,eters in this script
defined_parameters_function(){
defined_parameters=$(sed -n '/^### Configuration Parameters Start ###/,/^### Configuration Parameters End ###/p' "${0}" | \
grep -v '^\#' | awk -F'=' '{print $1}')
defined_parameters="${filename_variable} ${defined_parameters}"
}
# Run cleanup jobs
cleanup_function(){
unset ${defined_parameters}
}
### Functions End ###
### Script Body Start ###
request_filename_function
file_check
retry_function
left_handside_numbers_function "${!filename_variable}"
defined_parameters_function
cleanup_function
### Script Body End ###
exit 0

Related

Stream edit text file and replace string with increments

I want to duplicate markdown files to ~200 files and replace some strings in the document with incrementing changes. How should i do this? I am a new web developer, and my familiarity is just so-so with PHP and Node.js, but decent Linux user. I am thinking of using sed but can't wrap my mind around it.
Let's say i want to duplicate:
post.md "this is post _INCREMENT_"
then I run:
run generate "post.md" --number 2
to generate:
post1.md "this is post 1"
post2.md "this is post 2"
Combining sed and bash, would you please try the following:
#!/bin/bash
# show usage on improper arguments
usage() {
echo "usage: $1 filename.md number"
exit 1
}
file=$1 # obtain filename
[[ -n $file ]] || usage "$0" # filename is not specified
num=$2 || usage "$0" # obtain end bumber
(( num > 0 )) || usage "$0" # number is not specified or illegal
for (( i = 1; i <= num; i++ )); do
new="${file%.md}$i.md" # new filename with the serial number
cp -p -- "$file" "$new" # duplicate the file
sed -i "s/_INCREMENT_/$i/" "$new"
# replace "_INCREMENT_" with the serial number
done
Save the script above as a file generate or whatever, then run:
bash generate post.md 2

How to input the "realpath" of each file from a "while-loop" ind BASH script?

DESCRIPTION: Currently needing to input (or) pass the "realpath" of each file found hit found into a text file named "RESULTS.txt" that can be accessed by the user after the script runs.
ISSUE: Currently the syntax that i'm using to pass the code into the text file is failing. When I go to access the file it is blank. The following is the current code that is being used.
while read -r filename
do
filecount=$((filecount+1))
tput rc # return cursor to previously saved terminal line (tput sc)
# print filename (1st line of output); if shorter than previous filename we need to erase rest of line
filename="${filename%$'\r'}"
printf "file: ${filename}${erase}\n"
realpath "$filename" > RESULTS.txt
# print our status bar (2nd line of output) on the first and every ${modcount} pass through loop;
if [ ${filecount} -eq 1 ]
then
printf "[${barhash}${barspace}]\n"
elif [[ $((filecount % ${modcount} )) -eq 0 ]]
then
# for every ${modcount}th file we ...
barspace=${barspace:1:100000} # strip a space from barspace
barhash="${barhash}#" # add a '#' to barhash
printf "[${barhash}${barspace}]\n" # print our new status bar
fi
done < <(find "$dir_choice" -type f | sort -V )
...Pretty sure that the mistake that I am making is silly and is matter of syntax along with place ment not sure if I should be using realpath "$filname" >> RESULTS instead realpath "$filename" > RESULTS.txt

Shell script that filters command output and saves it in Json formated list

never worked with shell scripts before,but i need to in my current task.
So i have to run a command that returns output like this:
awd54a7w6ds54awd47awd refs/heads/SomeInfo1
awdafawe23413f13a3r3r refs/heads/SomeInfo2
a8wd5a8w5da78d6asawd7 refs/heads/SomeInfo3
g9reh9wrg69egs7ef987e refs/heads/SomeInfo4
And i need to loop over every line of output get only the "SomeInfo" part and write it to a file in a format like this:
["SomeInfo1","SomeInfo2","SomeInfo3"]
I've tried things like this:
for i in $(some command); do
echo $i | cut -f2 -d"heads/" >> text.txt
done
But i don't know how to format it into an array without using a temporary file.
Sorry if the question is dumb and probably too easy and im sure i can figure it out on my own,but i just don't have the time for it because its just an extra conveniance feature that i personally want to implement.
Try this
# json_encoder.sh
arr=()
while read line; do
arr+=(\"$(basename "$line")\")
done
printf "[%s]" $(IFS=,; echo "${arr[*]}")
And then invoke
./your_command | json_encoder.sh
PS. I personally do this kind of data massaging with Vim.
Using Perl one-liner
$ cat petar.txt
awd54a7w6ds54awd47awd refs/heads/SomeInfo1
awdafawe23413f13a3r3r refs/heads/SomeInfo2
a8wd5a8w5da78d6asawd7 refs/heads/SomeInfo3
g9reh9wrg69egs7ef987e refs/heads/SomeInfo4
$ perl -ne ' { /.*\/(.*)/ and push(#res,"\"$1\"") } END { print "[".join(",",#res)."]\n" }' petar.txt
["SomeInfo1","SomeInfo2","SomeInfo3","SomeInfo4"]
While you should rarely ever use a script to format json, in your case you are simply parsing output into a comma-separated line with added end-caps of [...]. You can use bash parameter expansion to avoid spawning any additional subshells to obtain the last field of information in each line as follows:
#!/bin/bash
[ -z "$1" -o ! -r "$1" ] && { ## validate file given as argument
printf "error: file doesn't exist or not readable.\n" >&2
exit 1
}
c=0 ## simple flag variable
while read -r line; do ## read each line
if [ "$c" -eq '0' ]; then ## is flag 0?
printf "[\"%s\"" "${line##*/}" ## output ["last"
else ## otherwise
printf ",\"%s\"" "${line##*/}" ## output ,"last"
fi
c=1 ## set flag 1
done < file ## redirect file to loop
echo "]" ## append closing ]
Example Use/Output
Using your given data as the input file, you would get the following:
$ bash script.sh file
["SomeInfo1","SomeInfo2","SomeInfo3","SomeInfo4"]
Look things over and let me know if you have any questions.
You can also use awk without any loops I guess:
cat prev_output | awk -v ORS=',' -F'/' '{print "\042"$3"\042"}' | \
sed 's/^/[/g ; s/,$/]\n/g' > new_output
cat new_output
["SomeInfo1","SomeInfo2","SomeInfo3","SomeInfo4"]

linux shell script: getting filename from a user input string

I would like to write a shell script in which I'll take a line input from user,which will contain some xxx.cpp as filename.
I want to get that "xxx" in another variable.
e.g.
if user give input as:
some params path/to/file/xyz.cpp more p/ara/ms
I want to get xyz which occurs before".cpp" and after last occurance of "/" before ".cpp"
Use basename [param] [.ext].
echo `basename $1 .cpp`
where 1 is the index of path/to/file.xyz in the argument list.
Here's a sample bash script to prompt the user for a list of files and filter all the input and display only the base name of files that end in '.cpp' (with .cpp removed) and which are readable
#!/bin/bash
echo Enter list of files:
read list_of_files
for file in $(echo $list_of_files); do
if echo $file | grep '\.cpp$' > /dev/null; then
if [[ -r $file ]]; then
fn=$(basename ${file})
fn=${fn%.*}
echo $fn
fi
fi
done

How to read using "read" from file descriptor 3 in bash script?

http://bash.cyberciti.biz/file-management/shell-script-to-simulate-unix-more-command/
#!/bin/bash
# Write a shell script like a more command. It asks the user name, the
# name of the file on command prompt and displays only the 15 lines of
# the file at a time.
# -------------------------------------------------------------------------
# Copyright (c) 2007 nixCraft project <http://cyberciti.biz/fb/>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# -------------------------------------------------------------------------
counter=1
echo -n "Enter a file name : "
read file
if [ ! -f $file ]
then
echo "$file not a file!"
exit 1
fi
# read file line by line
exec 3<&0
while read line
do
# pause at line no. 15
if [ $counter -eq 15 ]
then
counter=0 # reset counter
echo " *** Press [Enter] key to continue ..."
read -u 3 enterKey
fi
echo $line
(( counter++ ))
done < $file
This emulates more command..
I get this error..
read: 26: Illegal option -u
Make sure to enter the name of a file which has more than 15 lines..
Also I read the man page of "read" and i didnt get an option like "-u"..
So, how do i read using "read" from the file descriptor 3 (which is copy of stdin).
try
read key <&3
It's also possible to get bash to assign a file descriptor to a variable;
The next free descriptor number will be allocated starting from 10.
For example:
#!/bin/bash
FILENAME="my_file.txt"
exec {FD}<${FILENAME} # open file for read, assign descriptor
echo "Opened ${FILENAME} for read using descriptor ${FD}"
while read -u ${FD} LINE
do
# do something with ${LINE}
echo ${LINE}
done
exec {FD}<&- # close file
Just for the record, here's yet another more script:
# Author: Steve Stock
# http://www.linuxjournal.com/article/7385 (comments)
shmore() {
LINES=""
while read -d $'\n' line; do
printf "%s\n" "$line"
#echo "$line"
LINES=".${LINES}"
if [[ "$LINES" == "......................." ]]; then
echo -n "--More--"
read < /dev/tty
LINES=""
fi
done
return 0
}
shmore < file.txt
found here: http://codesnippets.joyent.com/posts/show/1788

Resources